<commit_before>// Global vars
var pymChild = null;
var isMobile = false;
var dataSeries = [];

/*
 * Initialize graphic
 */
var onWindowLoaded = function() {
    if (Modernizr.svg) {
        formatData();

        pymChild = new pym.Child({
            renderCallback: render
        });
    } else {
        pymChild = new pym.Child({});
    }

    pymChild.onMessage('on-screen', function(bucket) {
        ANALYTICS.trackEvent('on-screen', bucket);
    });
    pymChild.onMessage('scroll-depth', function(data) {
        data = JSON.parse(data);
        ANALYTICS.trackEvent('scroll-depth', data.percent, data.seconds);
    });
}

/*
 * Format graphic data for processing by D3.
 */
var formatData = function() {
    DATA.forEach(function(d) {
        d['date'] = d3.time.format('%m/%d/%y').parse(d['date']);

        for (var key in d) {
            if (key != 'date' && d[key] != null && d[key].length > 0) {
                d[key] = +d[key];
            }
        }
    });

    /*
     * Restructure tabular data for easier charting.
     */
    for (var column in DATA[0]) {
        if (column == 'date') {
            continue;
        }

        dataSeries.push({
            'name': column,
            'values': DATA.map(function(d) {
                return {
                    'date': d['date'],
                    'amt': d[column]
                };
    // filter out empty data. uncomment this if you have inconsistent data.
    //        }).filter(function(d) {
    //            return d['amt'] != null;
            })
        });
    }
}

/*
 * Render the graphic(s). Called by pym with the container width.
 */
var render = function(containerWidth) {
    if (!containerWidth) {
        containerWidth = DEFAULT_WIDTH;
    }

    if (containerWidth <= MOBILE_THRESHOLD) {
        isMobile = true;
    } else {
        isMobile = false;
    }

    // Render the chart!
    renderLineChart({
        container: '#line-chart',
        width: containerWidth,
        data: dataSeries
    });

    // Update iframe
    if (pymChild) {
        pymChild.sendHeight();
    }
}

/*
 * Render a line chart.
 */
var renderLineChart = function(config) {
    /*
     * Setup
     */
    var dateColumn = 'date';
    var valueColumn = 'amt';

    var aspectWidth = isMobile ? 4 : 16;
    var aspectHeight = isMobile ? 3 : 9;

    var margins = {
        top: 5,
        right: 75,
        bottom: 20,
        left: 30
    };

    var ticksX = 10;
    var ticksY = 10;
    var roundTicksFactor = 5;

    // Mobile
    if (isMobile) {
        ticksX = 5;
        ticksY = 5;
        margins['right'] = 25;
    }

    // Calculate actual chart dimensions
    var chartWidth = config['width'] - margins['left'] - margins['right'];
    var chartHeight = Math.ceil((config['width'] * aspectHeight) / aspectWidth) - margins['top'] - margins['bottom'];

    // Clear existing graphic (for redraw)
    var containerElement = d3.select(config['container']);
    containerElement.html('');

    /*
     * Create D3 scale objects.
     */
    var xScale = d3.time.scale()
        .domain(d3.extent(config['data'][0]['values'], function(d) {
            return d['date'];
        }))
        .range([ 0, chartWidth ])

    var min = d3.min(config['data'], function(d) {
        return d3.min(d['values'], function(v) {
            return Math.floor(v[valueColumn] / roundTicksFactor) * roundTicksFactor;
        })
    });

    if (min > 0) {
        min = 0;
    }

    var max = d3.max(config['data'], function(d) {
        return d3.max(d['values'], function(v) {
            return Math.ceil(v[valueColumn] / roundTicksFactor) * roundTicksFactor;
        })
    });

    var yScale = d3.scale.linear()
        .domain([min, max])
        .range([chartHeight, 0]);

    var colorScale = d3.scale.ordinal()
        .domain(_.pluck(config['data'], 'name'))
        .range([COLORS['red3'], COLORS['yellow3'], COLORS['blue3'], COLORS['orange3'], COLORS['teal3']]);

    /*
     * Render the HTML legend.
     */
    var legend = containerElement.append('ul')
        .attr('class', 'key')
        .selectAll('g')
        .data(config['data'])
        .enter().append('li')
            .attr('class', function(d, i) {
                return 'key-item ' + classify(d['name']);
            });

    legend.append('b')
        .style('background-color', function(d) {
            return colorScale(d['name']);
        });

    legend.append('label')
        .text(function(d) {
            return d['name'];
        });

    /*
     * Create the root SVG element.
     */
    var chartWrapper = containerElement.append('div')
        .attr('class', 'graphic-wrapper');

    var chartElement = chartWrapper.append('svg')
        .attr('width', chartWidth + margins['left'] + margins['right'])
        .attr('height', chartHeight + margins['top'] + margins['bottom'])
        .append('g')
        .attr('transform', 'translate(' + margins['left'] + ',' + margins['top'] + ')');

    /*
     * Create D3 axes.
     */
    var xAxis = d3.svg.axis()
        .scale(xScale)
        .orient('bottom')
        .ticks(ticksX)
        .tickFormat(function(d, i) {
            if (isMobile) {
                return '\u2019' + fmtYearAbbrev(d);
            } else {
                return fmtYearFull(d);
            }
        });

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .orient('left')
        .ticks(ticksY);

    /*
     * Render axes to chart.
     */
    chartElement.append('g')
        .attr('class', 'x axis')
        .attr('transform', makeTranslate(0, chartHeight))
        .call(xAxis);

    chartElement.append('g')
        .attr('class', 'y axis')
        .call(yAxis);

    /*
     * Render grid to chart.
     */
    var xAxisGrid = function() {
        return xAxis;
    }

    var yAxisGrid = function() {
        return yAxis;
    }

    chartElement.append('g')
        .attr('class', 'x grid')
        .attr('transform', makeTranslate(0, chartHeight))
        .call(xAxisGrid()
            .tickSize(-chartHeight, 0, 0)
            .tickFormat('')
        );

    chartElement.append('g')
        .attr('class', 'y grid')
        .call(yAxisGrid()
            .tickSize(-chartWidth, 0, 0)
            .tickFormat('')
        );

    /*
     * Render lines to chart.
     */
    var line = d3.svg.line()
        .interpolate('monotone')
        .x(function(d) {
            return xScale(d[dateColumn]);
        })
        .y(function(d) {
            return yScale(d[valueColumn]);
        });

    chartElement.append('g')
        .attr('class', 'lines')
        .selectAll('path')
        .data(config['data'])
        .enter()
        .append('path')
            .attr('class', function(d, i) {
                return 'line ' + classify(d['name']);
            })
            .attr('stroke', function(d) {
                return colorScale(d['name']);
            })
            .attr('d', function(d) {
                return line(d['values']);
            });

    chartElement.append('g')
        .attr('class', 'value')
        .selectAll('text')
        .data(config['data'])
        .enter().append('text')
            .attr('x', function(d, i) {
                var last = d['values'][d['values'].length - 1];

                return xScale(last[dateColumn]) + 5;
            })
            .attr('y', function(d) {
                var last = d['values'][d['values'].length - 1];

                return yScale(last[valueColumn]) + 3;
            })
            .text(function(d) {
                var last = d['values'][d['values'].length - 1];
                var value = last[valueColumn];

                var label = last[valueColumn].toFixed(1);

                if (!isMobile) {
                    label = d['name'] + ': ' + label;
                }

                return label;
            });
}

/*
 * Initially load the graphic
 * (NB: Use window.load to ensure all images have loaded)
 */
window.onload = onWindowLoaded;
<commit_msg>line chart template: add zero line<commit_after>// Global vars
var pymChild = null;
var isMobile = false;
var dataSeries = [];

/*
 * Initialize graphic
 */
var onWindowLoaded = function() {
    if (Modernizr.svg) {
        formatData();

        pymChild = new pym.Child({
            renderCallback: render
        });
    } else {
        pymChild = new pym.Child({});
    }

    pymChild.onMessage('on-screen', function(bucket) {
        ANALYTICS.trackEvent('on-screen', bucket);
    });
    pymChild.onMessage('scroll-depth', function(data) {
        data = JSON.parse(data);
        ANALYTICS.trackEvent('scroll-depth', data.percent, data.seconds);
    });
}

/*
 * Format graphic data for processing by D3.
 */
var formatData = function() {
    DATA.forEach(function(d) {
        d['date'] = d3.time.format('%m/%d/%y').parse(d['date']);

        for (var key in d) {
            if (key != 'date' && d[key] != null && d[key].length > 0) {
                d[key] = +d[key];
            }
        }
    });

    /*
     * Restructure tabular data for easier charting.
     */
    for (var column in DATA[0]) {
        if (column == 'date') {
            continue;
        }

        dataSeries.push({
            'name': column,
            'values': DATA.map(function(d) {
                return {
                    'date': d['date'],
                    'amt': d[column]
                };
    // filter out empty data. uncomment this if you have inconsistent data.
    //        }).filter(function(d) {
    //            return d['amt'] != null;
            })
        });
    }
}

/*
 * Render the graphic(s). Called by pym with the container width.
 */
var render = function(containerWidth) {
    if (!containerWidth) {
        containerWidth = DEFAULT_WIDTH;
    }

    if (containerWidth <= MOBILE_THRESHOLD) {
        isMobile = true;
    } else {
        isMobile = false;
    }

    // Render the chart!
    renderLineChart({
        container: '#line-chart',
        width: containerWidth,
        data: dataSeries
    });

    // Update iframe
    if (pymChild) {
        pymChild.sendHeight();
    }
}

/*
 * Render a line chart.
 */
var renderLineChart = function(config) {
    /*
     * Setup
     */
    var dateColumn = 'date';
    var valueColumn = 'amt';

    var aspectWidth = isMobile ? 4 : 16;
    var aspectHeight = isMobile ? 3 : 9;

    var margins = {
        top: 5,
        right: 75,
        bottom: 20,
        left: 30
    };

    var ticksX = 10;
    var ticksY = 10;
    var roundTicksFactor = 5;

    // Mobile
    if (isMobile) {
        ticksX = 5;
        ticksY = 5;
        margins['right'] = 25;
    }

    // Calculate actual chart dimensions
    var chartWidth = config['width'] - margins['left'] - margins['right'];
    var chartHeight = Math.ceil((config['width'] * aspectHeight) / aspectWidth) - margins['top'] - margins['bottom'];

    // Clear existing graphic (for redraw)
    var containerElement = d3.select(config['container']);
    containerElement.html('');

    /*
     * Create D3 scale objects.
     */
    var xScale = d3.time.scale()
        .domain(d3.extent(config['data'][0]['values'], function(d) {
            return d['date'];
        }))
        .range([ 0, chartWidth ])

    var min = d3.min(config['data'], function(d) {
        return d3.min(d['values'], function(v) {
            return Math.floor(v[valueColumn] / roundTicksFactor) * roundTicksFactor;
        })
    });

    if (min > 0) {
        min = 0;
    }

    var max = d3.max(config['data'], function(d) {
        return d3.max(d['values'], function(v) {
            return Math.ceil(v[valueColumn] / roundTicksFactor) * roundTicksFactor;
        })
    });

    var yScale = d3.scale.linear()
        .domain([min, max])
        .range([chartHeight, 0]);

    var colorScale = d3.scale.ordinal()
        .domain(_.pluck(config['data'], 'name'))
        .range([COLORS['red3'], COLORS['yellow3'], COLORS['blue3'], COLORS['orange3'], COLORS['teal3']]);

    /*
     * Render the HTML legend.
     */
    var legend = containerElement.append('ul')
        .attr('class', 'key')
        .selectAll('g')
        .data(config['data'])
        .enter().append('li')
            .attr('class', function(d, i) {
                return 'key-item ' + classify(d['name']);
            });

    legend.append('b')
        .style('background-color', function(d) {
            return colorScale(d['name']);
        });

    legend.append('label')
        .text(function(d) {
            return d['name'];
        });

    /*
     * Create the root SVG element.
     */
    var chartWrapper = containerElement.append('div')
        .attr('class', 'graphic-wrapper');

    var chartElement = chartWrapper.append('svg')
        .attr('width', chartWidth + margins['left'] + margins['right'])
        .attr('height', chartHeight + margins['top'] + margins['bottom'])
        .append('g')
        .attr('transform', 'translate(' + margins['left'] + ',' + margins['top'] + ')');

    /*
     * Create D3 axes.
     */
    var xAxis = d3.svg.axis()
        .scale(xScale)
        .orient('bottom')
        .ticks(ticksX)
        .tickFormat(function(d, i) {
            if (isMobile) {
                return '\u2019' + fmtYearAbbrev(d);
            } else {
                return fmtYearFull(d);
            }
        });

    var yAxis = d3.svg.axis()
        .scale(yScale)
        .orient('left')
        .ticks(ticksY);

    /*
     * Render axes to chart.
     */
    chartElement.append('g')
        .attr('class', 'x axis')
        .attr('transform', makeTranslate(0, chartHeight))
        .call(xAxis);

    chartElement.append('g')
        .attr('class', 'y axis')
        .call(yAxis);

    /*
     * Render grid to chart.
     */
    var xAxisGrid = function() {
        return xAxis;
    }

    var yAxisGrid = function() {
        return yAxis;
    }

    chartElement.append('g')
        .attr('class', 'x grid')
        .attr('transform', makeTranslate(0, chartHeight))
        .call(xAxisGrid()
            .tickSize(-chartHeight, 0, 0)
            .tickFormat('')
        );

    chartElement.append('g')
        .attr('class', 'y grid')
        .call(yAxisGrid()
            .tickSize(-chartWidth, 0, 0)
            .tickFormat('')
        );

    /*
     * Render 0 value line.
     */
    if (min < 0) {
        chartElement.append('line')
            .attr('class', 'zero-line')
            .attr('x1', 0)
            .attr('x2', chartWidth)
            .attr('y1', yScale(0))
            .attr('y2', yScale(0));
    }

    /*
     * Render lines to chart.
     */
    var line = d3.svg.line()
        .interpolate('monotone')
        .x(function(d) {
            return xScale(d[dateColumn]);
        })
        .y(function(d) {
            return yScale(d[valueColumn]);
        });

    chartElement.append('g')
        .attr('class', 'lines')
        .selectAll('path')
        .data(config['data'])
        .enter()
        .append('path')
            .attr('class', function(d, i) {
                return 'line ' + classify(d['name']);
            })
            .attr('stroke', function(d) {
                return colorScale(d['name']);
            })
            .attr('d', function(d) {
                return line(d['values']);
            });

    chartElement.append('g')
        .attr('class', 'value')
        .selectAll('text')
        .data(config['data'])
        .enter().append('text')
            .attr('x', function(d, i) {
                var last = d['values'][d['values'].length - 1];

                return xScale(last[dateColumn]) + 5;
            })
            .attr('y', function(d) {
                var last = d['values'][d['values'].length - 1];

                return yScale(last[valueColumn]) + 3;
            })
            .text(function(d) {
                var last = d['values'][d['values'].length - 1];
                var value = last[valueColumn];

                var label = last[valueColumn].toFixed(1);

                if (!isMobile) {
                    label = d['name'] + ': ' + label;
                }

                return label;
            });
}

/*
 * Initially load the graphic
 * (NB: Use window.load to ensure all images have loaded)
 */
window.onload = onWindowLoaded;
<|endoftext|>


<commit_before>var MIN_TIME_BETWEEN_PAGE_RENDERING_AND_POST = 5; // in seconds

var express = require('express');
var app = express();

app.set('views', GLOBAL.views_dir_path);
app.set('view engine', 'jade');

var db = require('./db').connect();
var crypto = require('crypto');
var keys = require('./keys');
var lang_module = require('./lang');

var mail = require("nodemailer").mail;

exports.returnJSON = function(res,obj)
{
  var body = JSON.stringify(obj);
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Content-Length', body.length);
  res.end(body);
}

exports.renderJade = function(req,res,page,options)
{
	// Store the last time a page was rendered in session
	// Used to detect robots when receiving post messages from non-admin users
	req.session.lastPageRenderTime = new Date().getTime();
	options.timestamp304 = req.session.lastPageRenderTime;

	if (req.params.lang)
		options.lang = req.params.lang;
	else
		options.lang = lang_module.get(req);

	keys.getAllKeysAndValues(req,function(err,values)
	{
		if (!err)
		{
			var keys = values;
			if (! keys ) keys = {};

			options.keys = keys;
			res.render(page,options);
		}
		else
		{
			options.keys = {};
			res.render(page,options);
		}
	});
}

exports.killFastRobots = function(req,res,next)
{
	if (req.session.lastPageRenderTime)
	{
		var lastPageRenderTime = new Date(req.session.lastPageRenderTime);
		var now = new Date();

		var diff = (now - lastPageRenderTime) / 1000;

		if (diff >= MIN_TIME_BETWEEN_PAGE_RENDERING_AND_POST)
		{
			next();
		}
		else
		{
			var obj = {"success":false};

			var body = JSON.stringify(obj);
			res.setHeader('Content-Type', 'application/json');
			res.setHeader('Content-Length', body.length);
			res.end(body);
		}
	}
	else
	{
		var obj = {"success":false};

		var body = JSON.stringify(obj);
		res.setHeader('Content-Type', 'application/json');
		res.setHeader('Content-Length', body.length);
		res.end(body);

	}
}

// html is optional
exports.sendMail = function(to,from,title,text,html)
{
	var mailObject = {};
	mailObject.from = from;
	mailObject.to = to;
	mailObject.subject = title;
	mailObject.text = text;

	if (html)
		mailObject.html = html;

	//console.dir(mailObject);

	mail(mailObject);
}

exports.randomHash = function(nbBytes)
{
	return crypto.randomBytes(nbBytes).toString('hex');
}

exports.sha1 = function(string)
{
	var shasum = crypto.createHash('sha1');
	shasum.update(string);
	return shasum.digest('hex');
}

<commit_msg>Added md5(string) to tools<commit_after>var MIN_TIME_BETWEEN_PAGE_RENDERING_AND_POST = 5; // in seconds

var express = require('express');
var app = express();

app.set('views', GLOBAL.views_dir_path);
app.set('view engine', 'jade');

var db = require('./db').connect();
var crypto = require('crypto');
var keys = require('./keys');
var lang_module = require('./lang');

var mail = require("nodemailer").mail;

exports.returnJSON = function(res,obj)
{
  var body = JSON.stringify(obj);
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Content-Length', body.length);
  res.end(body);
}

exports.renderJade = function(req,res,page,options)
{
	// Store the last time a page was rendered in session
	// Used to detect robots when receiving post messages from non-admin users
	req.session.lastPageRenderTime = new Date().getTime();
	options.timestamp304 = req.session.lastPageRenderTime;

	if (req.params.lang)
		options.lang = req.params.lang;
	else
		options.lang = lang_module.get(req);

	keys.getAllKeysAndValues(req,function(err,values)
	{
		if (!err)
		{
			var keys = values;
			if (! keys ) keys = {};

			options.keys = keys;
			res.render(page,options);
		}
		else
		{
			options.keys = {};
			res.render(page,options);
		}
	});
}

exports.killFastRobots = function(req,res,next)
{
	if (req.session.lastPageRenderTime)
	{
		var lastPageRenderTime = new Date(req.session.lastPageRenderTime);
		var now = new Date();

		var diff = (now - lastPageRenderTime) / 1000;

		if (diff >= MIN_TIME_BETWEEN_PAGE_RENDERING_AND_POST)
		{
			next();
		}
		else
		{
			var obj = {"success":false};

			var body = JSON.stringify(obj);
			res.setHeader('Content-Type', 'application/json');
			res.setHeader('Content-Length', body.length);
			res.end(body);
		}
	}
	else
	{
		var obj = {"success":false};

		var body = JSON.stringify(obj);
		res.setHeader('Content-Type', 'application/json');
		res.setHeader('Content-Length', body.length);
		res.end(body);

	}
}

// html is optional
exports.sendMail = function(to,from,title,text,html)
{
	var mailObject = {};
	mailObject.from = from;
	mailObject.to = to;
	mailObject.subject = title;
	mailObject.text = text;

	if (html)
		mailObject.html = html;

	//console.dir(mailObject);

	mail(mailObject);
}

exports.randomHash = function(nbBytes)
{
	return crypto.randomBytes(nbBytes).toString('hex');
}

exports.sha1 = function(string)
{
	var shasum = crypto.createHash('sha1');
	shasum.update(string);
	return shasum.digest('hex');
}

exports.md5 = function(string)
{
	var sum = crypto.createHash('md5');
	sum.update(string);
	return sum.digest('hex');
}

<|endoftext|>


<commit_before>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var sys = require('sys');
var http = require('http');
var url = require('url');

var sprintf = require('sprintf').sprintf;

var log = require('util/log');

var Check = require('health').Check;
var CheckResult = require('health').CheckResult;
var CheckStatus = require('health').CheckStatus;

var config = {
  name: 'HTTP check',
  requiredArguments: ['url', 'type', 'match_value'],
  optionalArguments: [],
  defaultValues: {},
  types: {
    STATUS_CODE_MATCH: 0,
    BODY_REGEX_MATCH: 1
  }
};

/**
 * HTTP(s) check.
 *
 * @param {Object} checkArguments Provided check arguments.
 *
 * @constructor
 */
function HTTPCheck(checkArguments) {
  Check.call(this, config.name, config.requiredArguments,
             config.optionalArguments, config.defaultValues, checkArguments);
}

// Inherit from the base Check class
sys.inherits(HTTPCheck, Check);

HTTPCheck.prototype.run = function(callback) {
  log.info(sprintf('Running HTTP check (URL: %s, type: %s, match_value: %s)',
           this.checkArguments.url,
           this.checkArguments.type,
           this.checkArguments['match_value']));

  var self = this;
  var result = new CheckResult();
  var timeout = false;

  // @TODO: ssl support
  var options = {
    'host': self.checkArguments.host,
    'port': parseInt(self.checkArguments.port, 10),
    'method': 'GET',
    'path': self.checkArguments.path
  };

  var req = http.request(options, function onResponse(response) {
    if (self.checkArguments.type === config.types.STATUS_CODE_MATCH) {
      var statusCode = response.statusCode;

      if (statusCode === self.checkArguments['match_value']) {
        result.status = CheckStatus.SUCCESS;
        result.details = sprintf('Returned status code: %s', statusCode);
      }
      else {
        result.status = CheckStatus.ERROR;
        result.details = sprintf('Returned status code:  %s', statusCode);
      }

      self.addResult(result, callback);
    }
    else if (self.checkArguments.type === config.types.BODY_REGEX_MATCH) {
      // We only care about the content if it's a body regex match check
      var dataBuffer = [];

      response.on('data', function(chunk) {
        dataBuffer.push(chunk);
      });

      response.on('end', function() {
        var body = dataBuffer.join('');

        if (body.match(self.checkArguments['match_value'])) {
          result.status = CheckStatus.SUCCESS;
          result.details = sprintf('The response body matched the regular expression: %s',
                                  self.checkArguments['match_value'].toString());
        }
        else {
          result.status = CheckStatus.ERROR;
          result.details = sprintf('The response body didn\'t match the regular expression: %s',
                                   self.checkArguments['match_value'].toString());
        }

        self.addResult(result, callback);
      });
    }
  });

  function errorHandler(exception) {
    result.status = CheckStatus.ERROR;
    result.details = sprintf('Check failed - returned exception: %s', exception);

    self.addResult(result, callback);
  }

  // Register generic error event handlers
  req.on('error', errorHandler);

  // Send the request
  req.end();

  /*client.on('timeout', function() {
    timeout = true;
    // Close the connection, the check status is set in the client end event handler
    client.end();
  });*/

  /*client.on('end', function() {
    if (self.lastRunDate !== result.date) {
      // If the result hasn't been added yet at this stage this means that the check has failed
      result.status = CheckStatus.ERROR;

      if (timeout === true) {
        result.details = sprintf('Timeout after %s seconds', self.checkArguments.timeout / 1000);
      }
      else {
        result.details = sprintf('Unknown error');
      }

      self.addResult(result, callback);
    }

    if (req.connection._writeQueue.length > 0) {
      // If for some strange reason all the buffer wasn't flushed out, manually destroy the connection
      // (yeah, it's an ugly hack)
      req.connection.destroy();
    }
  });*/
};

HTTPCheck.prototype.formatArguments = function(requiredArguments, optionalArguments,
                                                defaultValues, checkArguments) {
  var formattedArguments = Check.prototype.formatArguments.call(this, requiredArguments,
                                          optionalArguments, defaultValues,
                                          checkArguments);

  var urlObject = url.parse(formattedArguments.url);

  formattedArguments.host = urlObject.hostname;
  formattedArguments.path = urlObject.pathname || '/';

  formattedArguments.secure = (urlObject.protocol === 'https:') || false;
  formattedArguments.port = urlObject.port || (formattedArguments.secure === true ? 443 : 80);

  if (formattedArguments.type === config.types.STATUS_CODE_MATCH) {
    formattedArguments['match_value'] = parseInt(formattedArguments['match_value'], 10);
  }
  else if (checkArguments.type === config.types.BODY_REGEX_MATCH) {
    formattedArguments['match_value'] = new RegExp(formattedArguments['match_value']);
  }
  else {
    throw new Error(sprintf('Invalid check type: %s', formattedArguments.type));
  }

  return formattedArguments;
};

exports.config = config;
exports.HTTPCheck = HTTPCheck;
<commit_msg>Add support for ssl to the http health check.<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var sys = require('sys');
var http = require('http');
var https = require('https');
var url = require('url');

var sprintf = require('sprintf').sprintf;

var log = require('util/log');

var Check = require('health').Check;
var CheckResult = require('health').CheckResult;
var CheckStatus = require('health').CheckStatus;

var config = {
  name: 'HTTP check',
  requiredArguments: ['url', 'type', 'match_value'],
  optionalArguments: [],
  defaultValues: {},
  types: {
    STATUS_CODE_MATCH: 0,
    BODY_REGEX_MATCH: 1
  }
};

/**
 * HTTP(s) check.
 *
 * @param {Object} checkArguments Provided check arguments.
 *
 * @constructor
 */
function HTTPCheck(checkArguments) {
  Check.call(this, config.name, config.requiredArguments,
             config.optionalArguments, config.defaultValues, checkArguments);
}

// Inherit from the base Check class
sys.inherits(HTTPCheck, Check);

HTTPCheck.prototype.run = function(callback) {
  var method;
  var self = this;
  log.info(sprintf('Running HTTP check (URL: %s, type: %s, match_value: %s)',
           this.checkArguments.url,
           this.checkArguments.type,
           this.checkArguments['match_value']));

  var result = new CheckResult();
  var timeout = false;

  var options = {
    'host': self.checkArguments.host,
    'port': parseInt(self.checkArguments.port, 10),
    'method': 'GET',
    'path': self.checkArguments.path
  };

  method = (self.checkArguments.secure) ? https.request : http.request;

  var req = method(options, function onResponse(response) {
    if (self.checkArguments.type === config.types.STATUS_CODE_MATCH) {
      var statusCode = response.statusCode;

      if (statusCode === self.checkArguments['match_value']) {
        result.status = CheckStatus.SUCCESS;
        result.details = sprintf('Returned status code: %s', statusCode);
      }
      else {
        result.status = CheckStatus.ERROR;
        result.details = sprintf('Returned status code:  %s', statusCode);
      }

      self.addResult(result, callback);
    }
    else if (self.checkArguments.type === config.types.BODY_REGEX_MATCH) {
      // We only care about the content if it's a body regex match check
      var dataBuffer = [];

      response.on('data', function(chunk) {
        dataBuffer.push(chunk);
      });

      response.on('end', function() {
        var body = dataBuffer.join('');

        if (body.match(self.checkArguments['match_value'])) {
          result.status = CheckStatus.SUCCESS;
          result.details = sprintf('The response body matched the regular expression: %s',
                                  self.checkArguments['match_value'].toString());
        }
        else {
          result.status = CheckStatus.ERROR;
          result.details = sprintf('The response body didn\'t match the regular expression: %s',
                                   self.checkArguments['match_value'].toString());
        }

        self.addResult(result, callback);
      });
    }
  });

  function errorHandler(exception) {
    result.status = CheckStatus.ERROR;
    result.details = sprintf('Check failed - returned exception: %s', exception);

    self.addResult(result, callback);
  }

  // Register generic error event handlers
  req.on('error', errorHandler);

  // Send the request
  req.end();

  /*client.on('timeout', function() {
    timeout = true;
    // Close the connection, the check status is set in the client end event handler
    client.end();
  });*/

  /*client.on('end', function() {
    if (self.lastRunDate !== result.date) {
      // If the result hasn't been added yet at this stage this means that the check has failed
      result.status = CheckStatus.ERROR;

      if (timeout === true) {
        result.details = sprintf('Timeout after %s seconds', self.checkArguments.timeout / 1000);
      }
      else {
        result.details = sprintf('Unknown error');
      }

      self.addResult(result, callback);
    }

    if (req.connection._writeQueue.length > 0) {
      // If for some strange reason all the buffer wasn't flushed out, manually destroy the connection
      // (yeah, it's an ugly hack)
      req.connection.destroy();
    }
  });*/
};

HTTPCheck.prototype.formatArguments = function(requiredArguments, optionalArguments,
                                                defaultValues, checkArguments) {
  var formattedArguments = Check.prototype.formatArguments.call(this, requiredArguments,
                                          optionalArguments, defaultValues,
                                          checkArguments);

  var urlObject = url.parse(formattedArguments.url);

  formattedArguments.host = urlObject.hostname;
  formattedArguments.path = urlObject.pathname || '/';

  formattedArguments.secure = (urlObject.protocol === 'https:') || false;
  formattedArguments.port = urlObject.port || (formattedArguments.secure === true ? 443 : 80);

  if (formattedArguments.type === config.types.STATUS_CODE_MATCH) {
    formattedArguments['match_value'] = parseInt(formattedArguments['match_value'], 10);
  }
  else if (checkArguments.type === config.types.BODY_REGEX_MATCH) {
    formattedArguments['match_value'] = new RegExp(formattedArguments['match_value']);
  }
  else {
    throw new Error(sprintf('Invalid check type: %s', formattedArguments.type));
  }

  return formattedArguments;
};

exports.config = config;
exports.HTTPCheck = HTTPCheck;
<|endoftext|>


<commit_before>/*
CinsImp
xTalk Compiler Dictionary

*********************************************************************************
Copyright (c) 2009-2015, Joshua Hawcroft
All rights reserved.

 May all beings have happiness and the cause of happiness.
 May all beings be free of suffering and the cause of suffering.
 May all beings rejoice for the supreme happiness which is without suffering.
 May all beings abide in the great equanimity; free of attachment and delusion.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the product nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

Xtalk.Dict = {

/*****************************************************************************************
Constants
*/

	_TERM: 1,
	_CONSTANT: 2,

/*****************************************************************************************
Module Globals
*/

	_constants: [],
	_properties: [],
	_references: [],
	_counts: [],

	/* Commands:

	   Two levels of access:
		 _commands[ <first word> ][n] := <definition>, where n is the definition index.

	   Command definitions consist of:
	   -	pattern (a tree produced by the parse-bnf module which describes the syntax)
	   -	parameters (an array of named arguments in the order they will be presented
	   		to the handling function)
	   -    delayed (an array of boolean flags indicating whether the corresponding
	   		argument value should be evaluated to a primitive type, or left as a
	   		reference type for further processing)
	   -	handler (a function to implement the command behaviour and to which the
	   		arguments will be provided)
	*/
	_commands: [],

/*****************************************************************************************
Registration
*/

	register_term: function(in_name, in_id, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		if (!this._constants[word_count])
			this._constants[word_count] = [];
		this._constants[word_count][in_name.toLowerCase()] = {
			type: 		this._TERM,
			id:			in_id,
			handler: 	in_handler
		};
	},

	register_constant: function(in_name, in_value)
	{
		var word_count = Xtalk._word_count(in_name);
		if (!this._constants[word_count])
			this._constants[word_count] = [];
		this._constants[word_count][in_name.toLowerCase()] = {
			type: 		this._CONSTANT,
			value: 		in_value
		};
	},

	register_property: function(in_name, in_id, in_context_type, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		var in_name = in_name.toLowerCase();
		var context_type_map = this._properties[in_name];
		if (!context_type_map)
		{
			context_type_map = [];
			this._properties[in_name] = context_type_map;
		}
		context_type_map[in_context_type] = {
			id:			in_id,
			handler:	in_handler
		};
	},

	register_reference: function(in_name, in_id, in_context_type, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		var in_name = in_name.toLowerCase();
		var context_type_map = this._references[in_name];
		if (!context_type_map)
		{
			context_type_map = [];
			this._references[in_name] = context_type_map;
		}
		context_type_map[in_context_type] = {
			id:			in_id,
			handler:	in_handler
		};
	},

	register_count: function(in_name, in_id, in_context_type, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		var in_name = in_name.toLowerCase();
		var context_type_map = this._counts[in_name];
		if (!context_type_map)
		{
			context_type_map = [];
			this._counts[in_name] = context_type_map;
		}
		context_type_map[in_context_type] = {
			id:			in_id,
			handler:	in_handler
		};
	},

/*
	Registers a command syntax, argument sequence, argument evaluation and handler.
 */
	register_command: function(in_syntax, in_arguments, in_handler)
	{
		in_syntax = in_syntax.toLowerCase();
		var first_word = in_syntax.split(' ', 1)[0].trim().toLowerCase();

		var args = in_arguments.split(',');
		var delayed = [];
		for (var a = 0; a < args.length; a++)
		{
			var arg_name = args[a].trim().toLowerCase();
			if (arg_name.substr(0, 1) == '|' &&
				arg_name.substr(arg_name.length-1, 1) == '|')
			{
				arg_name = arg_name.replace('|','').trim();
				delayed.push(true);
			}
			else
				delayed.push(false);
			args[a] = arg_name;
		}

		var def = {
			pattern: Xtalk.Parser.BNF.parse(in_syntax),
			parameters: args,
			delayed: delayed,
			handler: in_handler
		};
		this._commands[first_word] = def;
	},

/*
	Initalizes the dictionary with all language built-ins.
 */
	init_builtins: function()
	{
		this.register_command(
			'beep <number> [time[s]]',
			'number',
			function(n) { alert('BEEP! ' + JSON.stringify(n)); }
		);

		/*this.register_term('this bkgnd', 'bkgd', function() { alert('Get this bkgnd'); });
		this.register_constant('one', 1);

		this.register_property('date', 'date', '----', function() { alert('Get date'); });

		this.register_count('cards', 'cdct', 'BKGD', function() { alert('return bg card count'); });*/
	}

};

Xtalk.Dict.init_builtins();

<commit_msg>fixes to dictionary for command syntax debugging<commit_after>/*
CinsImp
xTalk Compiler Dictionary

*********************************************************************************
Copyright (c) 2009-2015, Joshua Hawcroft
All rights reserved.

 May all beings have happiness and the cause of happiness.
 May all beings be free of suffering and the cause of suffering.
 May all beings rejoice for the supreme happiness which is without suffering.
 May all beings abide in the great equanimity; free of attachment and delusion.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the product nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

Xtalk.Dict = {

/*****************************************************************************************
Constants
*/

	_TERM: 1,
	_CONSTANT: 2,

/*****************************************************************************************
Module Globals
*/

	_constants: [],
	_properties: [],
	_references: [],
	_counts: [],

	/* Commands:

	   Two levels of access:
		 _commands[ <first word> ][n] := <definition>, where n is the definition index.

	   Command definitions consist of:
	   -	pattern (a tree produced by the parse-bnf module which describes the syntax)
	   -	parameters (an array of named arguments in the order they will be presented
	   		to the handling function)
	   -    delayed (an array of boolean flags indicating whether the corresponding
	   		argument value should be evaluated to a primitive type, or left as a
	   		reference type for further processing)
	   -	handler (a function to implement the command behaviour and to which the
	   		arguments will be provided)
	*/
	_commands: [],

/*****************************************************************************************
Registration
*/

	register_term: function(in_name, in_id, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		if (!this._constants[word_count])
			this._constants[word_count] = [];
		this._constants[word_count][in_name.toLowerCase()] = {
			type: 		this._TERM,
			id:			in_id,
			handler: 	in_handler
		};
	},

	register_constant: function(in_name, in_value)
	{
		var word_count = Xtalk._word_count(in_name);
		if (!this._constants[word_count])
			this._constants[word_count] = [];
		this._constants[word_count][in_name.toLowerCase()] = {
			type: 		this._CONSTANT,
			value: 		in_value
		};
	},

	register_property: function(in_name, in_id, in_context_type, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		var in_name = in_name.toLowerCase();
		var context_type_map = this._properties[in_name];
		if (!context_type_map)
		{
			context_type_map = [];
			this._properties[in_name] = context_type_map;
		}
		context_type_map[in_context_type] = {
			id:			in_id,
			handler:	in_handler
		};
	},

	register_reference: function(in_name, in_id, in_context_type, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		var in_name = in_name.toLowerCase();
		var context_type_map = this._references[in_name];
		if (!context_type_map)
		{
			context_type_map = [];
			this._references[in_name] = context_type_map;
		}
		context_type_map[in_context_type] = {
			id:			in_id,
			handler:	in_handler
		};
	},

	register_count: function(in_name, in_id, in_context_type, in_handler)
	{
		var word_count = Xtalk._word_count(in_name);
		var in_name = in_name.toLowerCase();
		var context_type_map = this._counts[in_name];
		if (!context_type_map)
		{
			context_type_map = [];
			this._counts[in_name] = context_type_map;
		}
		context_type_map[in_context_type] = {
			id:			in_id,
			handler:	in_handler
		};
	},

/*
	Registers a command syntax, argument sequence, argument evaluation and handler.
 */
	register_command: function(in_syntax, in_arguments, in_handler)
	{
		in_syntax = in_syntax.toLowerCase();
		var first_word = in_syntax.split(' ', 1)[0].trim().toLowerCase();

		var args = in_arguments.split(',');
		var delayed = [];
		for (var a = 0; a < args.length; a++)
		{
			var arg_name = args[a].trim().toLowerCase();
			if (arg_name.substr(0, 1) == '|' &&
				arg_name.substr(arg_name.length-1, 1) == '|')
			{
				arg_name = arg_name.replace('|','').trim();
				delayed.push(true);
			}
			else
				delayed.push(false);
			args[a] = arg_name;
		}

		var def = {
			pattern: Xtalk.Parser.BNF.parse(in_syntax),
			parameters: args,
			delayed: delayed,
			handler: in_handler
		};
		if (!this._commands[first_word])
			this._commands[first_word] = [];
		this._commands[first_word].push( def );
	},

/*
	Initalizes the dictionary with all language built-ins.
 */
	init_builtins: function()
	{
		this.register_command(
			'beep <number> [time[s]]',
			'number',
			function(n) { alert('BEEP! ' + JSON.stringify(n)); }
		);

		/*this.register_term('this bkgnd', 'bkgd', function() { alert('Get this bkgnd'); });
		this.register_constant('one', 1);

		this.register_property('date', 'date', '----', function() { alert('Get date'); });

		this.register_count('cards', 'cdct', 'BKGD', function() { alert('return bg card count'); });*/
	}

};

Xtalk.Dict.init_builtins();

<|endoftext|>


<commit_before>import Promise from 'bluebird';
import sinon from 'sinon';
import { expect } from 'chai';

import endpointGenerator from '../src/endpointGenerator';

function rand() {
  return Math.random().toString(36).substring(7);
}

describe('endpointGenerator', () => {

  describe('generate', () => {

    it('should allow chaining single child', (done) => {
      const baseIn = rand();
      const childIn = rand();
      const baseReturn = rand();
      const childReturn = rand();

      let baseCount = 0;
      let childCount = 0;

      function base(inputValue) {
        expect(inputValue).to.equal(baseIn);
        baseCount++;
        return baseReturn;
      }

      function child(inputValue) {
        expect(inputValue).to.equal(childIn);
        childCount++;
        return childReturn;
      }

      const base = endpointGenerator.generate(base, [child]);

      return Promise.try(base, [baseIn])
        .then((baseValue) => {
          expect(baseValue).to.equal(baseReturn);

          return base(baseIn).child(childIn)
        })
        .then((childValue) => {
          expect(childValue).to.equal(childReturn);
        })
        .then(() => {
          expect(baseCount).to.equal(1);
          expect(childCount).to.equal(1);
          done();
        })
        .catch(done);

    });

  });

});
<commit_msg>Added tests to work with chained children<commit_after>import Promise from 'bluebird';
import sinon from 'sinon';
import { expect } from 'chai';

import endpointGenerator from '../src/endpointGenerator';

function rand() {
  return Math.random().toString(36).substring(7);
}

describe('endpointGenerator', () => {

  describe('generate', () => {

    it('should allow chaining single child', (done) => {
      const baseIn = rand();
      const childIn = rand();
      const baseReturn = rand();
      const childReturn = rand();

      let baseCount = 0;
      let childCount = 0;

      function base(inputValue) {
        expect(inputValue).to.equal(baseIn);
        baseCount++;
        return baseReturn;
      }

      function child(inputValue) {
        expect(inputValue).to.equal(childIn);
        childCount++;
        return childReturn;
      }

      const base = endpointGenerator.generate(base, { child });

      return Promise.try(base, [baseIn])
        .then((baseValue) => {
          expect(baseValue).to.equal(baseReturn);

          const baseOut = base(baseIn);
          expect(baseOut).to.be.an('object');
          expect(baseOut.child).to.be.a('function');
          return baseOut.child(childIn)
        })
        .then((childValue) => {
          expect(childValue).to.equal(childReturn);
        })
        .then(() => {
          expect(baseCount).to.equal(1);
          expect(childCount).to.equal(1);
          done();
        })
        .catch(done);

    });

    it('should allow chaining grand child', (done) => {
      const baseIn = rand();
      const childIn = rand();
      const grandChildIn = rand();
      const baseReturn = rand();
      const childReturn = rand();
      const grandchildReturn = rand();

      let baseCount = 0;
      let childCount = 0;
      let grandchildCount = 0;

      function base(inputValue) {
        expect(inputValue).to.equal(baseIn);
        baseCount++;
        return baseReturn;
      }

      function child(inputValue) {
        expect(inputValue).to.equal(childIn);
        childCount++;
        return childReturn;
      }

      function grandchild(inputValue) {
        expect(inputValue).to.equal(grandChildIn);
        grandchildCount++;
        return grandchildReturn;
      }

      const child = endpointGenerator.generate(child, { grandchild});
      const base = endpointGenerator.generate(base, { child });

      return Promise.try(base, [baseIn])
        .then((baseValue) => {
          expect(baseValue).to.equal(baseReturn);

          const baseOut = base(baseIn);
          expect(baseOut).to.be.an('object');
          expect(baseOut.child).to.be.a('function');

          return baseOut.child(childIn)
        })
        .then((childValue) => {
          expect(childValue).to.equal(childReturn);

          return base(baseIn).child(childIn).grandchild(grandChildIn);
        })
        .then((grandChildValue) => {
          expect(grandChildValue).to.equal(grandchildReturn);
        })
        .then(() => {
          expect(baseCount).to.equal(1);
          expect(childCount).to.equal(1);
          expect(grandchildCount).to.equal(1);
          done();
        })
        .catch(done);

    });

  });

});
<|endoftext|>


<commit_before>(function () {

	var makeKeyDefinition = function ( code ) {
		return function ( node, fire ) {
			var keydownHandler;

			node.addEventListener( 'keydown', keydownHandler = function ( event ) {
				var which = event.which || event.keyCode;

				if ( which === code ) {
					event.preventDefault();

					fire({
						node: node,
						original: event
					});
				}
			}, false );

			return {
				teardown: function () {
					node.removeEventListener( 'keydown', keydownHandler, false );
				}
			};
		};
	};

	eventDefinitions.enter = makeKeyDefinition( 13 );
	eventDefinitions.tab = makeKeyDefinition( 9 );
	eventDefinitions.escape = makeKeyDefinition( 27 );
	eventDefinitions.space = makeKeyDefinition( 32 );

}());<commit_msg>add arrow key event definitions<commit_after>(function () {

	var makeKeyDefinition = function ( code ) {
		return function ( node, fire ) {
			var keydownHandler;

			node.addEventListener( 'keydown', keydownHandler = function ( event ) {
				var which = event.which || event.keyCode;

				if ( which === code ) {
					event.preventDefault();

					fire({
						node: node,
						original: event
					});
				}
			}, false );

			return {
				teardown: function () {
					node.removeEventListener( 'keydown', keydownHandler, false );
				}
			};
		};
	};

	eventDefinitions.enter = makeKeyDefinition( 13 );
	eventDefinitions.tab = makeKeyDefinition( 9 );
	eventDefinitions.escape = makeKeyDefinition( 27 );
	eventDefinitions.space = makeKeyDefinition( 32 );

	eventDefinitions.leftarrow = makeKeyDefinition( 37 );
	eventDefinitions.rightarrow = makeKeyDefinition( 39 );
	eventDefinitions.downarrow = makeKeyDefinition( 40 );
	eventDefinitions.uparrow = makeKeyDefinition( 38 );

}());<|endoftext|>


<commit_before>'use strict';

const http = require('http');
const fs = require('mz/fs');
const url = require('url');
const path = require('path');
const logger = require('koa-logger')();
const app = require('koa')();
const Router = require('koa-router');
const clients = [];

app.use(logger);

app.use(function*(next) {

  try {
    yield* next;
  } catch (e) {
    if (e.status) { // User error
      this.body = e.message;
      this.status = e.status;
    } else { // Server error
      this.body = "Error 500";
      this.status = 500;
      console.error(e.message, e.stack);
    }

  }

});

let router = new Router();

router
  .get('/', function* (next) {
    let indexFile = path.join(__dirname, 'index.html');
    let getIndexFile = fs.createReadStream(indexFile);
    this.type = 'html';
    this.body = getIndexFile;
  })
  .get('/subscribe', function* (next) {
    clients.push(this);
    yield prom;
    //if(clients[0]['response']['message'] === 'Not found' || clients[0]['response']['message'] === 'OK'){
    //  yield* next;
    //}else{
    //  this.body = clients[0]['response']['message'];
    //}
    this.body = prom;
    //yield* next;
  });
let prom;

  router.post('/publish', function* (next) {
    let ct = '';
    prom = new Promise(function (resolve, reject) {
      this.req
        .on('data', function(data){
          ct += data;
        })
        .on('end', function(){
          console.log(clients);
          //clients[0]['response']['message'] = ct;
          resolve(ct);
        })
      reject('test!');
    })
    //this.body = 'lol';
  });

app.use(router.routes());

app.listen(3000);

//const server = http.createServer(function(req, res) {
//
//  const urlPath = url.parse(req.url).pathname;
//
//  switch (req.method + ' ' + urlPath) {
//  case 'GET /':
//    res.setHeader('Content-Type', 'text/html; charset=utf-8');
//    sendFile("index.html", res);
//    break;
//
//  case 'GET /subscribe':
//
//    res.on('close', function() {
//      // console.log("subscribe - close");
//      clients.splice(clients.indexOf(res), 1);
//    });
//
//    clients.push(res);
//
//    console.log("subscribe", clients.length);
//
//    break;
//
//  case 'POST /publish':
//    // console.log("publish");
//    req.setEncoding('utf-8');
//
//    var body = '';
//
//    req
//      .on('data', function(data) {
//        // -----> размер body может быть слишком большим
//        body += data;
//
//        if (body.length > 512) { // маленькое значение важно для теста, т.к. end срабатывает
//          res.statusCode = 413;
//          res.end("Your message is too big for my little chat");
//        }
//      })
//      .on('end', function() {
//        // "end" triggers when all data consumed
//        // even if it's too big
//        if (res.statusCode == 413) return;
//
//        try {
//          body = JSON.parse(body);
//          if (!body.message) {
//            throw new SyntaxError("No message");
//          }
//          body.message = String(body.message);
//        } catch (e) {
//          res.statusCode = 400;
//          res.end("Bad Request");
//          return;
//        }
//
//        // console.log("publish '%s' to %d", body.message, clients.length);
//
//        // заметим: не может быть,
//        // чтобы в процессе этого цикла добавились новые соединения или закрылись текущие
//        clients.forEach(function(res) {
//          res.setHeader('Cache-Control', "no-cache, no-store, private");
//          res.end(body.message);
//        });
//
//        clients.length = 0;
//
//        res.end("ok");
//      });
//
//    break;
//
//  default:
//    res.statusCode = 404;
//    res.end("Not found");
//  }
//
//
//});
//
//// for tests if needed
//server._clients = clients;
//
//module.exports = server;
//
//function sendFile(fileName, res) {
//  var fileStream = fs.createReadStream(fileName);
//  fileStream
//    .on('error', function() {
//      res.statusCode = 500;
//      res.end("Server error");
//    })
//    .pipe(res)
//    .on('close', function() {
//      fileStream.destroy();
//    });
//}
<commit_msg>add promise<commit_after>'use strict';

const http = require('http');
const fs = require('mz/fs');
const url = require('url');
const path = require('path');
const logger = require('koa-logger')();
const app = require('koa')();
const Router = require('koa-router');
const clients = [];

app.use(logger);

app.use(function*(next) {

  try {
    yield* next;
  } catch (e) {
    if (e.status) { // User error
      this.body = e.message;
      this.status = e.status;
    } else { // Server error
      this.body = "Error 500";
      this.status = 500;
      console.error(e.message, e.stack);
    }

  }

});

let router = new Router();
let prom;

router
  .get('/', function* (next) {
    let indexFile = path.join(__dirname, 'index.html');
    let getIndexFile = fs.createReadStream(indexFile);
    this.type = 'html';
    this.body = getIndexFile;
  })
  .get('/subscribe', function* (next) {
    clients.push(this);
    //console.log(clients[0]['res'].end());
    //console.log(clients[0]['res']);
    this.body = yield new Promise(function(resolve, reject) {
      if(clients[0]['res']['finished']){
        resolve(clients[0]['response']['message']);
      }else{
        reject('bad');
      }
    })

    console.log(this.body);
  });

  router.post('/publish', function* (next) {
    let ct = '';
      this.req
        .on('data', function(data){
          ct += data;
        })
        .on('end', function(){
          //console.log(clients);
          clients[0]['response']['message'] = ct;
          clients[0]['res'].end();
          this.body = ct;
        })
    //this.body = 'lol';
  });

app.use(router.routes());

app.listen(3000);

//const server = http.createServer(function(req, res) {
//
//  const urlPath = url.parse(req.url).pathname;
//
//  switch (req.method + ' ' + urlPath) {
//  case 'GET /':
//    res.setHeader('Content-Type', 'text/html; charset=utf-8');
//    sendFile("index.html", res);
//    break;
//
//  case 'GET /subscribe':
//
//    res.on('close', function() {
//      // console.log("subscribe - close");
//      clients.splice(clients.indexOf(res), 1);
//    });
//
//    clients.push(res);
//
//    console.log("subscribe", clients.length);
//
//    break;
//
//  case 'POST /publish':
//    // console.log("publish");
//    req.setEncoding('utf-8');
//
//    var body = '';
//
//    req
//      .on('data', function(data) {
//        // -----> размер body может быть слишком большим
//        body += data;
//
//        if (body.length > 512) { // маленькое значение важно для теста, т.к. end срабатывает
//          res.statusCode = 413;
//          res.end("Your message is too big for my little chat");
//        }
//      })
//      .on('end', function() {
//        // "end" triggers when all data consumed
//        // even if it's too big
//        if (res.statusCode == 413) return;
//
//        try {
//          body = JSON.parse(body);
//          if (!body.message) {
//            throw new SyntaxError("No message");
//          }
//          body.message = String(body.message);
//        } catch (e) {
//          res.statusCode = 400;
//          res.end("Bad Request");
//          return;
//        }
//
//        // console.log("publish '%s' to %d", body.message, clients.length);
//
//        // заметим: не может быть,
//        // чтобы в процессе этого цикла добавились новые соединения или закрылись текущие
//        clients.forEach(function(res) {
//          res.setHeader('Cache-Control', "no-cache, no-store, private");
//          res.end(body.message);
//        });
//
//        clients.length = 0;
//
//        res.end("ok");
//      });
//
//    break;
//
//  default:
//    res.statusCode = 404;
//    res.end("Not found");
//  }
//
//
//});
//
//// for tests if needed
//server._clients = clients;
//
//module.exports = server;
//
//function sendFile(fileName, res) {
//  var fileStream = fs.createReadStream(fileName);
//  fileStream
//    .on('error', function() {
//      res.statusCode = 500;
//      res.end("Server error");
//    })
//    .pipe(res)
//    .on('close', function() {
//      fileStream.destroy();
//    });
//}
<|endoftext|>


<commit_before>import { onConnect, onMessage, sendToTab } from 'crossmessaging';
import getOptions from '../options/getOptions';
import { MENU_DEVTOOLS } from '../../../app/constants/ContextMenus.js';
let connections = {};

const naMessage = {
  na: true,
  source: 'redux-page'
};

// Connect to devpanel
onConnect((tabId) => {
  console.log('init!', window.store.id, tabId);
  if (tabId !== store.id) return naMessage;
  return {
    payload: window.store.liftedStore.getState(),
    source: 'redux-page'
  };
}, {}, connections);

function parseJSON(data) {
  try {
    return JSON.parse(data);
  } catch (e) {
    // console.error(data + 'is not a valid JSON', e);
    return null;
  }
}

// Receive message from content script and relay to the devTools page
function messaging(request, sender, sendResponse) {
  const tabId = sender.tab ? sender.tab.id : sender.id;
  if (tabId) {
    if (request.type === 'PAGE_UNLOADED') {
      if (connections[ tabId ]) connections[ tabId ].postMessage(naMessage);
      return true;
    }
    if (request.type === 'GET_OPTIONS') {
      getOptions(options => {
        sendResponse({options: options});
      });
      return true;
    }
    const payload = typeof request.payload === 'string' ? parseJSON(request.payload) : request.payload;
    if (!payload) return true;
    store.liftedStore.setState(payload);
    if (request.init) {
      store.id = tabId;
      if (typeof tabId === 'number') {
        chrome.contextMenus.update(MENU_DEVTOOLS, {documentUrlPatterns: [sender.url], enabled: true});
        chrome.pageAction.show(tabId);
      }
    }
    if (tabId in connections) {
      connections[ tabId ].postMessage({payload: payload});
    }
  }
  return true;
}

onMessage(messaging);
chrome.runtime.onMessageExternal.addListener(messaging);

export function toContentScript(action) {
  if (store.id in connections) {
    connections[ store.id ].postMessage({action: action});
  } else {
    sendToTab(store.id, {action: action});
  }
}
<commit_msg>Nuke console.log<commit_after>import { onConnect, onMessage, sendToTab } from 'crossmessaging';
import getOptions from '../options/getOptions';
import { MENU_DEVTOOLS } from '../../../app/constants/ContextMenus.js';
let connections = {};

const naMessage = {
  na: true,
  source: 'redux-page'
};

// Connect to devpanel
onConnect((tabId) => {
  if (tabId !== store.id) return naMessage;
  return {
    payload: window.store.liftedStore.getState(),
    source: 'redux-page'
  };
}, {}, connections);

function parseJSON(data) {
  try {
    return JSON.parse(data);
  } catch (e) {
    // console.error(data + 'is not a valid JSON', e);
    return null;
  }
}

// Receive message from content script and relay to the devTools page
function messaging(request, sender, sendResponse) {
  const tabId = sender.tab ? sender.tab.id : sender.id;
  if (tabId) {
    if (request.type === 'PAGE_UNLOADED') {
      if (connections[ tabId ]) connections[ tabId ].postMessage(naMessage);
      return true;
    }
    if (request.type === 'GET_OPTIONS') {
      getOptions(options => {
        sendResponse({options: options});
      });
      return true;
    }
    const payload = typeof request.payload === 'string' ? parseJSON(request.payload) : request.payload;
    if (!payload) return true;
    store.liftedStore.setState(payload);
    if (request.init) {
      store.id = tabId;
      if (typeof tabId === 'number') {
        chrome.contextMenus.update(MENU_DEVTOOLS, {documentUrlPatterns: [sender.url], enabled: true});
        chrome.pageAction.show(tabId);
      }
    }
    if (tabId in connections) {
      connections[ tabId ].postMessage({payload: payload});
    }
  }
  return true;
}

onMessage(messaging);
chrome.runtime.onMessageExternal.addListener(messaging);

export function toContentScript(action) {
  if (store.id in connections) {
    connections[ store.id ].postMessage({action: action});
  } else {
    sendToTab(store.id, {action: action});
  }
}
<|endoftext|>


<commit_before>/**
 * Creates and loads an image element by url.
 * @param  {String} url
 * @return {Promise} promise that resolves to an image element or
 *                   fails to an Error.
 */
var request_image = function(url) {
    return new Promise(function(resolve, reject) {
        var img = new Image();
        img.onload = function() { resolve(img); };
        img.onerror = function() { reject(url); };
        img.src = url + '?random-no-cache=' + Math.floor((1 + Math.random()) * 0x10000).toString(16);
    });
};

/**
 * Pings a url.
 * @param  {String} url
 * @return {Promise} promise that resolves to a ping (ms, float).
 */
var ping = function(url) {
    return new Promise(function(resolve, reject) {
        var start = (new Date()).getTime();
        var response = function() {
            var delta = ((new Date()).getTime() - start);

            // HACK: Use a fudge factor to correct the ping for HTTP bulk.
            delta /= 4;

            resolve(delta);
        };
        request_image(url).then(response).catch(response);

        // Set a timeout for max-pings, 5s.
        setTimeout(function() { reject(Error('Timeout')); }, 5000);
    });
};
<commit_msg>Update ping.js<commit_after>/**
 * Creates and loads an image element by url.
 * @param  {String} url
 * @return {Promise} promise that resolves to an image element or
 *                   fails to an Error.
 */
var request_image = function(url) {
    return new Promise(function(resolve, reject) {
        var img = new Image();
        img.onload = function() { resolve(img); };
        img.onerror = function() { reject(url); };
        img.src = url + '?random-no-cache=' + Math.floor((1 + Math.random()) * 0x10000).toString(16);
    });
};

/**
 * Pings a url.
 * @param  {String} url
 * @param  {Number} multiplier - optional, factor to adjust the ping by.  0.3 works well for HTTP servers.
 * @return {Promise} promise that resolves to a ping (ms, float).
 */
var ping = function(url, multiplier) {
    return new Promise(function(resolve, reject) {
        var start = (new Date()).getTime();
        var response = function() {
            var delta = ((new Date()).getTime() - start);
            delta *= (multiplier || 1);
            resolve(delta);
        };
        request_image(url).then(response).catch(response);

        // Set a timeout for max-pings, 5s.
        setTimeout(function() { reject(Error('Timeout')); }, 5000);
    });
};
<|endoftext|>


<commit_before>'use strict'

let basic = require('./basic-response-helper')

module.exports = {

  /**
   * Sends recently finished executions
   *
   * @param req
   * @param res
   */
  getRecent: (req, res) => {
    basic.getListCustom(req, res, 'pipeline_executions', function(query) {
      return query
        .orderBy('finished_at', 'desc')
        .take(10)
    })
  }

}<commit_msg>Syntax error<commit_after>'use strict'

let basic = require('./basic-response-helper')

module.exports = {

  /**
   * Sends recently finished executions
   *
   * @param req
   * @param res
   */
  getRecent: (req, res) => {
    basic.getListCustom(req, res, 'pipeline_executions', function(query) {
      return query
        .orderBy('finished_at', 'desc')
        .limit(10)
    })
  }

}<|endoftext|>


<commit_before>var request = require("request");
var url = require("url");

function RedditPlugin(bot) {
	var self = this;
	self.name = "reddit";
	self.help = "Reddit plugin";
	self.depend = ["cmd", "ignore", "date"];

	self.urlRe = /\b(https?|ftp):\/\/[^\s\/$.?#].[^\s]*\.[^\s]*\b/i;
	self.urlRedditRe = /reddit\.com\/(r\/[^\s\/]+\/)?comments\//i;
	self.urlSort = "hot";
	self.urlTime = "week";

	self.channels = [];
	self.ignores = [];

	self.tickers = {};
	self.interval = null;

	self.request = request.defaults({headers: {"User-Agent": "simbot reddit 1.0"}});

	self.load = function(data) {
		self.urlSort = data.urlSort;
		self.urlTime = data.urlTime;
		self.channels = data.channels;
		self.ignores = data.ignores;
		self.tickers = data.tickers || {};
	};

	self.enable = function() {
		self.tickerCheck();
		self.interval = setInterval(self.tickerCheck, 1 * 60 * 1000);
	};

	self.disable = function() {
		clearInterval(self.interval);
		self.interval = null;
	};

	self.save = function() {
		var tickers = {};
		for (var listing in self.tickers)
			tickers[listing] = {channels: self.tickers[listing].channels};

		return {
			urlSort: self.urlSort,
			urlTime: self.urlTime,
			channels: self.channels,
			ignores: self.ignores,
			tickers: tickers};
	};

	self.unescapeHtml = function(html) {
		return html.replace(/&([#\w]+);/g, function(_, n) {
			n = n.toLowerCase();
			if (n === 'amp') return '&';
			if (n === 'colon') return ':';
			if (n === 'lt') return '<';
			if (n === 'gt') return '>';
			if (n === 'quot') return '"';
			if (n.charAt(0) === '#') {
				return n.charAt(1) === 'x' ?
					String.fromCharCode(parseInt(n.substring(2), 16)) :
					String.fromCharCode(+n.substring(1));
			}
			return '';
		});
	};

	self.formatPost = function(post) {
		var warning = post.over_18 ? " \x034[NSFW]\x03" : "";
		var str = "\x1Fhttp://redd.it/" + post.id + "\x1F" + warning + " : \x02" + self.unescapeHtml(post.title) + "\x02 [r/" + post.subreddit + "] by " + post.author + " " + bot.plugins.date.printDur(new Date(post.created_utc * 1000), null, 1) + " ago; " + post.num_comments + " comments; " + post.score + " score";

		return str;
	};

	self.formatComment = function(comment) {
		var warning = false ? " \x034[NSFW]\x03" : "";
		var str = "\x1F" + comment.link_url + "comments/" + comment.id + "\x1F" + warning + " : \x02" + self.unescapeHtml(comment.link_title) + "\x02 [r/" + comment.subreddit + "] by " + comment.author + " " + bot.plugins.date.printDur(new Date(comment.created_utc * 1000), null, 1) + " ago; " + comment.score + " score";

		return str;
	};

	self.format = function(item) {
		return (item.kind == "t1" ? self.formatComment : self.formatPost)(item.data);
	};

	self.cleanUrl = function(lurl) {
		var obj = url.parse(lurl);
		obj.search = obj.query = obj.hash = null;
		return encodeURI(url.format(obj));
	};

	self.lookupOther = function(lurl, callback) {
		self.request({uri: "https://www.reddit.com/search.json", qs: {"q": "url:'" + lurl + "'", "limit": 3, "sort": self.urlSort, "t": self.urlTime}}, function(err, res, body) {
			if (!err && res.statusCode == 200) {
				var data = JSON.parse(body).data;
				var results = data.children;

				for (var i = 0; i < results.length; i++) {
					var post = results[i].data;

					if (post.url.indexOf(lurl) >= 0) { // actually contains link (prevent reddit search stupidity)
						(callback || function(){})(self.formatPost(post));
						break;
					}
				}
			}
		});
	};

	self.lookupReddit = function(rurl, callback) {
		self.request(self.cleanUrl(rurl) + ".json", function(err, res, body) {
			if (!err && res.statusCode == 200) {
				var data = JSON.parse(body)[0].data;
				var results = data.children;

				if (results.length > 0) {
					(callback || function(){})(self.formatPost(results[0].data));
				}
			}
		});
	};

	self.lookup = function(url, callback) {
		(url.match(self.urlRedditRe) ? self.lookupReddit : self.lookupOther)(url, callback);
	};

	self.tickerStart = function(listing, channels) {
		self.tickerStop(listing);

		self.tickers[listing] = {
			channels: channels
		};
	};

	self.tickerStop = function(listing) {
		delete self.tickers[listing];
	};

	self.tickerCheck = function() {
		for (var listing in self.tickers) {
			(function(listing) {
				self.request("https://www.reddit.com" + listing + ".json", function(err, res, body) {
					if (!err && res.statusCode == 200) {
						var list = JSON.parse(body).data.children;
						var pList = self.tickers[listing].pList;

						if (pList) {
							for (var i = list.length - 1; i >= 0; i--) {
								var found = false;
								for (var j = 0; j < pList.length; j++) {
									if (pList[j].kind == list[i].kind && pList[j].data.id == list[i].data.id) {
										found = true;
										break;
									}
								}

								if (!found) {
									self.tickers[listing].channels.forEach(function(to) {
										bot.say(to, self.format(list[i]));
									});
								}
							}
						}

						self.tickers[listing].pList = list;
					}
				});
			})(listing);
		}
	};

	self.events = {
		"message": function(nick, to, text, message) {
			if ((self.channels.indexOf(to) != -1) && !bot.plugins.ignore.ignored(self.ignores, message)) {
				var match = text.match(self.urlRe);
				if (match) {
					self.lookup(match[0], function(str) {
						bot.out.log("reddit", nick + " in " + to + ": " + match[0]);
						bot.say(to, str);
					});
				}
			}
		},

		"pm": function(nick, text, message) {
			var match = text.match(self.urlRe);
			if (match) {
				self.lookup(match[0], function(str) {
					bot.out.log("reddit", nick + " in PM: " + match[0]);
					bot.say(nick, str);
				});
			}
		},
	};
}

module.exports = RedditPlugin;
<commit_msg>reddit: correct links to comments<commit_after>var request = require("request");
var url = require("url");

function RedditPlugin(bot) {
	var self = this;
	self.name = "reddit";
	self.help = "Reddit plugin";
	self.depend = ["cmd", "ignore", "date"];

	self.urlRe = /\b(https?|ftp):\/\/[^\s\/$.?#].[^\s]*\.[^\s]*\b/i;
	self.urlRedditRe = /reddit\.com\/(r\/[^\s\/]+\/)?comments\//i;
	self.urlSort = "hot";
	self.urlTime = "week";

	self.channels = [];
	self.ignores = [];

	self.tickers = {};
	self.interval = null;

	self.request = request.defaults({headers: {"User-Agent": "simbot reddit 1.0"}});

	self.load = function(data) {
		self.urlSort = data.urlSort;
		self.urlTime = data.urlTime;
		self.channels = data.channels;
		self.ignores = data.ignores;
		self.tickers = data.tickers || {};
	};

	self.enable = function() {
		self.tickerCheck();
		self.interval = setInterval(self.tickerCheck, 1 * 60 * 1000);
	};

	self.disable = function() {
		clearInterval(self.interval);
		self.interval = null;
	};

	self.save = function() {
		var tickers = {};
		for (var listing in self.tickers)
			tickers[listing] = {channels: self.tickers[listing].channels};

		return {
			urlSort: self.urlSort,
			urlTime: self.urlTime,
			channels: self.channels,
			ignores: self.ignores,
			tickers: tickers};
	};

	self.unescapeHtml = function(html) {
		return html.replace(/&([#\w]+);/g, function(_, n) {
			n = n.toLowerCase();
			if (n === 'amp') return '&';
			if (n === 'colon') return ':';
			if (n === 'lt') return '<';
			if (n === 'gt') return '>';
			if (n === 'quot') return '"';
			if (n.charAt(0) === '#') {
				return n.charAt(1) === 'x' ?
					String.fromCharCode(parseInt(n.substring(2), 16)) :
					String.fromCharCode(+n.substring(1));
			}
			return '';
		});
	};

	self.formatPost = function(post) {
		var warning = post.over_18 ? " \x034[NSFW]\x03" : "";
		var str = "\x1Fhttp://redd.it/" + post.id + "\x1F" + warning + " : \x02" + self.unescapeHtml(post.title) + "\x02 [r/" + post.subreddit + "] by " + post.author + " " + bot.plugins.date.printDur(new Date(post.created_utc * 1000), null, 1) + " ago; " + post.num_comments + " comments; " + post.score + " score";

		return str;
	};

	self.formatComment = function(comment) {
		var warning = false ? " \x034[NSFW]\x03" : "";
		var str = "\x1Fhttp://reddit.com/r/" + comment.subreddit + "/comments/" + comment.link_id + "//" + comment.id + "\x1F" + warning + " : \x02" + self.unescapeHtml(comment.link_title) + "\x02 [r/" + comment.subreddit + "] by " + comment.author + " " + bot.plugins.date.printDur(new Date(comment.created_utc * 1000), null, 1) + " ago; " + comment.score + " score";

		return str;
	};

	self.format = function(item) {
		return (item.kind == "t1" ? self.formatComment : self.formatPost)(item.data);
	};

	self.cleanUrl = function(lurl) {
		var obj = url.parse(lurl);
		obj.search = obj.query = obj.hash = null;
		return encodeURI(url.format(obj));
	};

	self.lookupOther = function(lurl, callback) {
		self.request({uri: "https://www.reddit.com/search.json", qs: {"q": "url:'" + lurl + "'", "limit": 3, "sort": self.urlSort, "t": self.urlTime}}, function(err, res, body) {
			if (!err && res.statusCode == 200) {
				var data = JSON.parse(body).data;
				var results = data.children;

				for (var i = 0; i < results.length; i++) {
					var post = results[i].data;

					if (post.url.indexOf(lurl) >= 0) { // actually contains link (prevent reddit search stupidity)
						(callback || function(){})(self.formatPost(post));
						break;
					}
				}
			}
		});
	};

	self.lookupReddit = function(rurl, callback) {
		self.request(self.cleanUrl(rurl) + ".json", function(err, res, body) {
			if (!err && res.statusCode == 200) {
				var data = JSON.parse(body)[0].data;
				var results = data.children;

				if (results.length > 0) {
					(callback || function(){})(self.formatPost(results[0].data));
				}
			}
		});
	};

	self.lookup = function(url, callback) {
		(url.match(self.urlRedditRe) ? self.lookupReddit : self.lookupOther)(url, callback);
	};

	self.tickerStart = function(listing, channels) {
		self.tickerStop(listing);

		self.tickers[listing] = {
			channels: channels
		};
	};

	self.tickerStop = function(listing) {
		delete self.tickers[listing];
	};

	self.tickerCheck = function() {
		for (var listing in self.tickers) {
			(function(listing) {
				self.request("https://www.reddit.com" + listing + ".json", function(err, res, body) {
					if (!err && res.statusCode == 200) {
						var list = JSON.parse(body).data.children;
						var pList = self.tickers[listing].pList;

						if (pList) {
							for (var i = list.length - 1; i >= 0; i--) {
								var found = false;
								for (var j = 0; j < pList.length; j++) {
									if (pList[j].kind == list[i].kind && pList[j].data.id == list[i].data.id) {
										found = true;
										break;
									}
								}

								if (!found) {
									self.tickers[listing].channels.forEach(function(to) {
										bot.say(to, self.format(list[i]));
									});
								}
							}
						}

						self.tickers[listing].pList = list;
					}
				});
			})(listing);
		}
	};

	self.events = {
		"message": function(nick, to, text, message) {
			if ((self.channels.indexOf(to) != -1) && !bot.plugins.ignore.ignored(self.ignores, message)) {
				var match = text.match(self.urlRe);
				if (match) {
					self.lookup(match[0], function(str) {
						bot.out.log("reddit", nick + " in " + to + ": " + match[0]);
						bot.say(to, str);
					});
				}
			}
		},

		"pm": function(nick, text, message) {
			var match = text.match(self.urlRe);
			if (match) {
				self.lookup(match[0], function(str) {
					bot.out.log("reddit", nick + " in PM: " + match[0]);
					bot.say(nick, str);
				});
			}
		},
	};
}

module.exports = RedditPlugin;
<|endoftext|>


<commit_before>/* This file is part of Indico.
 * Copyright (C) 2002 - 2016 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

(function($) {
    $.widget("indico.categorypicker", {

        options: {
            categoryId: 0
        },

        _create: function() {
            var self = this;
            var element = self.element;
            var opt = self.options;

            self.$searchInput = $('<input>', {
                class: 'js-search-category',
                type: 'text',
                placeholder: $T.gettext("Search")
            });
            self.$categoryList = $('<ul>', {class: 'group-list fixed-height'});
            self.$categoryNavigator = $('<div>', {class: 'category-navigator i-box just-group-list with-hover-effect'})
                .append($('<div>', {class: 'i-box-content'})
                    .append(self.$categoryList));
            self.goToCategory(opt.categoryId);
            self.element.append(self.$searchInput).append(self.$categoryNavigator);
        },

        _buildBreadcrumbs: function(path) {
            var self = this;
            var $breadcrumbs = $('<ul>', {class: 'breadcrumbs'});

            _.each(path, function(category) {
                $breadcrumbs.append($('<li>')
                    .append($('<a>', {
                        text: category.title,
                        data: {id: category.id},
                        title:  $T.gettext("Go to: {0}".format(category.title)),
                        href: '#'
                    }).on('click', function(evt) {
                        evt.preventDefault()
                        self.goToCategory($(this).data('id'));
                    }))
                );
            });

            return $breadcrumbs;
        },

        _buildCurrentCategory: function(category) {
            var self = this;

            var $category = $('<div>', {
                class: 'item current-category',
                data: {id: category.id}
            });
            var $titleWrapper = $('<div>', {class: 'title-wrapper'})
            $titleWrapper.append($('<span>', {
                class: 'title',
                text: category.title,
            }));
            $titleWrapper.append(self._buildBreadcrumbs(category.path));
            $category.append($titleWrapper);
            if (category.path.length) {
                var parent = _.last(category.path);
                var $buttonWrapper = $('<div>', {class: 'button-wrapper'});
                $buttonWrapper.append($('<a>', {
                    class: 'icon-arrow-up navigate-up',
                    title: $T.gettext("Go to parent: {0}".format(parent.title))
                }).on('click', function() {
                    self.goToCategory(parent.id);
                }));
                $category.append($buttonWrapper);
            }

            return $category;
        },

        _buildSubcategory: function(subcategory) {
            var self = this;

            var $subcategory = $('<li>', {
                class: 'item subcategory',
                data: {id: subcategory.id}
            }).append($('<span>', {
                class: 'title',
                text: subcategory.title,
            })).on('click', function() {
                self.goToCategory($(this).data('id'));
            });

            return $subcategory;
        },

        _renderNavigator: function(data) {
            var self = this;

            if (data.category) {
                self.$categoryList.before(self._buildCurrentCategory(data.category));
            }
            if (data.subcategories) {
                _.each(data.subcategories, function(subcategory) {
                    self.$categoryList.append(self._buildSubcategory(subcategory));
                });
            }
        },

        goToCategory: function(id) {
            var self = this;

            $('.category-navigator .item').animate({
                height: 0,
                paddingTop: 0,
                paddingBottom: 0,
                border: 0
            }, {
                complete: function() {
                    $(this).remove();
                }
            }).find('.title').fadeOut();

            $.ajax({
                url: build_url(Indico.Urls.Categories.info, {categId: id}),
                dataType: 'json',
                error: function(data) {
                    handleAjaxError(data);
                },
                success: function(data) {
                    if (data) {
                        self._renderNavigator(data);
                    }
                }
            });
        }
    });
})(jQuery);
<commit_msg>Category picker: Add caching<commit_after>/* This file is part of Indico.
 * Copyright (C) 2002 - 2016 European Organization for Nuclear Research (CERN).
 *
 * Indico is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 3 of the
 * License, or (at your option) any later version.
 *
 * Indico is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Indico; if not, see <http://www.gnu.org/licenses/>.
 */

(function($) {
    $.widget("indico.categorypicker", {

        options: {
            categoryId: 0
        },

        _create: function() {
            var self = this;
            var element = self.element;
            var opt = self.options;

            self.cache = {};
            self.$searchInput = $('<input>', {
                class: 'js-search-category',
                type: 'text',
                placeholder: $T.gettext("Search")
            });
            self.$categoryList = $('<ul>', {class: 'group-list fixed-height'});
            self.$categoryNavigator = $('<div>', {class: 'category-navigator i-box just-group-list with-hover-effect'})
                .append($('<div>', {class: 'i-box-content'})
                    .append(self.$categoryList));
            self.goToCategory(opt.categoryId);
            self.element.append(self.$searchInput).append(self.$categoryNavigator);
        },

        _buildBreadcrumbs: function(path) {
            var self = this;
            var $breadcrumbs = $('<ul>', {class: 'breadcrumbs'});

            _.each(path, function(category) {
                $breadcrumbs.append($('<li>')
                    .append($('<a>', {
                        text: category.title,
                        data: {id: category.id},
                        title:  $T.gettext("Go to: {0}".format(category.title)),
                        href: '#'
                    }).on('click', function(evt) {
                        evt.preventDefault();
                        self.goToCategory($(this).data('id'));
                    }))
                );
            });

            return $breadcrumbs;
        },

        _buildCurrentCategory: function(category) {
            var self = this;

            var $category = $('<div>', {
                class: 'item current-category',
                data: {id: category.id}
            });
            var $titleWrapper = $('<div>', {class: 'title-wrapper'});
            $titleWrapper.append($('<span>', {
                class: 'title',
                text: category.title,
            }));
            $titleWrapper.append(self._buildBreadcrumbs(category.path));
            $category.append($titleWrapper);
            if (category.path.length) {
                var parent = _.last(category.path);
                var $buttonWrapper = $('<div>', {class: 'button-wrapper'});
                $buttonWrapper.append($('<a>', {
                    class: 'icon-arrow-up navigate-up',
                    title: $T.gettext("Go to parent: {0}".format(parent.title))
                }).on('click', function() {
                    self.goToCategory(parent.id);
                }));
                $category.append($buttonWrapper);
            }

            return $category;
        },

        _buildSubcategory: function(subcategory) {
            var self = this;

            var $subcategory = $('<li>', {
                class: 'item subcategory',
                data: {id: subcategory.id}
            }).append($('<span>', {
                class: 'title',
                text: subcategory.title,
            })).on('click', function() {
                self.goToCategory($(this).data('id'));
            });

            return $subcategory;
        },

        _renderNavigator: function(data) {
            var self = this;

            if (data.category) {
                self.$categoryList.before(self._buildCurrentCategory(data.category));
            }
            if (data.subcategories) {
                _.each(data.subcategories, function(subcategory) {
                    self.$categoryList.append(self._buildSubcategory(subcategory));
                });
            }
        },

        goToCategory: function(id) {
            var self = this;

            $('.category-navigator .item').animate({
                height: 0,
                paddingTop: 0,
                paddingBottom: 0,
                border: 0
            }, {
                complete: function() {
                    $(this).remove();
                }
            }).find('.title').fadeOut();

            if (self.cache[id]) {
                self._renderNavigator(self.cache[id]);
            } else {
                $.ajax({
                    url: build_url(Indico.Urls.Categories.info, {categId: id}),
                    dataType: 'json',
                    error: function(data) {
                        handleAjaxError(data);
                    },
                    success: function(data) {
                        if (data) {
                            self.cache[id] = data;
                            self._renderNavigator(data);
                        }
                    }
                });
            }
        }
    });
})(jQuery);
<|endoftext|>


<commit_before>var _append = require('./internal/_append');
var _curry2 = require('./internal/_curry2');
var _dispatchable = require('./internal/_dispatchable');
var _reduce = require('./internal/_reduce');
var _xgroupBy = require('./internal/_xgroupBy');

/**
 * Splits a list into sub-lists stored in an object, based on the result of calling a String-returning function
 * on each element, and grouping the results according to values returned.
 *
 * Acts as a transducer if a transformer is given in list position.
 * @see R.transduce
 *
 * @func
 * @memberOf R
 * @category List
 * @sig (a -> s) -> [a] -> {s: a}
 * @param {Function} fn Function :: a -> String
 * @param {Array} list The array to group
 * @return {Object} An object with the output of `fn` for keys, mapped to arrays of elements
 *         that produced that key when passed to `fn`.
 * @example
 *
 *     var byGrade = R.groupBy(function(student) {
 *       var score = student.score;
 *       return score < 65 ? 'F' :
 *              score < 70 ? 'D' :
 *              score < 80 ? 'C' :
 *              score < 90 ? 'B' : 'A';
 *     });
 *     var students = [{name: 'Abby', score: 84},
 *                     {name: 'Eddy', score: 58},
 *                     // ...
 *                     {name: 'Jack', score: 69}];
 *     byGrade(students);
 *     // {
 *     //   'A': [{name: 'Dianne', score: 99}],
 *     //   'B': [{name: 'Abby', score: 84}]
 *     //   // ...,
 *     //   'F': [{name: 'Eddy', score: 58}]
 *     // }
 */
module.exports = _curry2(_dispatchable('groupBy', _xgroupBy, function groupBy(fn, list) {
    return _reduce(function(acc, elt) {
        var key = fn(elt);
        acc[key] = _append(elt, acc[key] || (acc[key] = []));
        return acc;
    }, {}, list);
}));
<commit_msg>Type signature fix for groupBy<commit_after>var _append = require('./internal/_append');
var _curry2 = require('./internal/_curry2');
var _dispatchable = require('./internal/_dispatchable');
var _reduce = require('./internal/_reduce');
var _xgroupBy = require('./internal/_xgroupBy');

/**
 * Splits a list into sub-lists stored in an object, based on the result of calling a String-returning function
 * on each element, and grouping the results according to values returned.
 *
 * Acts as a transducer if a transformer is given in list position.
 * @see R.transduce
 *
 * @func
 * @memberOf R
 * @category List
 * @sig (a -> s) -> [a] -> {s: [a]}
 * @param {Function} fn Function :: a -> String
 * @param {Array} list The array to group
 * @return {Object} An object with the output of `fn` for keys, mapped to arrays of elements
 *         that produced that key when passed to `fn`.
 * @example
 *
 *     var byGrade = R.groupBy(function(student) {
 *       var score = student.score;
 *       return score < 65 ? 'F' :
 *              score < 70 ? 'D' :
 *              score < 80 ? 'C' :
 *              score < 90 ? 'B' : 'A';
 *     });
 *     var students = [{name: 'Abby', score: 84},
 *                     {name: 'Eddy', score: 58},
 *                     // ...
 *                     {name: 'Jack', score: 69}];
 *     byGrade(students);
 *     // {
 *     //   'A': [{name: 'Dianne', score: 99}],
 *     //   'B': [{name: 'Abby', score: 84}]
 *     //   // ...,
 *     //   'F': [{name: 'Eddy', score: 58}]
 *     // }
 */
module.exports = _curry2(_dispatchable('groupBy', _xgroupBy, function groupBy(fn, list) {
    return _reduce(function(acc, elt) {
        var key = fn(elt);
        acc[key] = _append(elt, acc[key] || (acc[key] = []));
        return acc;
    }, {}, list);
}));
<|endoftext|>