<commit_before>/*
 * moleculer
 * Copyright (c) 2018 MoleculerJS (https://github.com/moleculerjs/moleculer)
 * MIT Licensed
 */

"use strict";

const C = require("../constants");

module.exports = function() {

	let broker;
	let windowTimer;
	const store = new Map();
	let logger;

	/**
	 * Create timer to clear endpoint store
	 *
	 * @param {Number} windowTime
	 */
	function createWindowTimer(windowTime) {
		if (!windowTimer) {
			windowTimer = setInterval(() => resetStore(), (windowTime || 60) * 1000);
			windowTimer.unref();
		}
	}

	/**
	 * Clear endpoint state store
	 */
	function resetStore() {
		if (!logger) return;

		logger.debug("Reset circuit-breaker endpoint states...");
		store.forEach((item, key) => {
			if (item.count == 0) {
				logger.debug(`Remove '${key}' endpoint state because it is not used`);
				store.delete(key);
				return;
			}

			logger.debug(`Clean '${key}' endpoint state.`);
			item.count = 0;
			item.failures = 0;
		});
	}

	/**
	 * Get Endpoint state from store. If not exists, create it.
	 *
	 * @param {Endpoint} ep
	 * @param {Object} opts
	 * @returns {Object}
	 */
	function getEpState(ep, opts) {
		let item = store.get(ep.name);
		if (!item) {
			item = {
				ep,
				opts,
				count: 0,
				failures: 0,
				state: C.CIRCUIT_CLOSE,
				cbTimer: null
			};
			store.set(ep.name, item);
		}
		return item;
	}

	/**
	 * Increment failure counter
	 *
	 * @param {Object} item
	 * @param {Error} err
	 * @param {Context} ctx
	 */
	function failure(item, err, ctx) {
		item.count++;
		item.failures++;

		checkThreshold(item, ctx);
	}

	/**
	 * Increment request counter and switch CB to CLOSE if it is on HALF_OPEN_WAIT.
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function success(item, ctx) {
		item.count++;

		if (item.state === C.CIRCUIT_HALF_OPEN_WAIT)
			circuitClose(item, ctx);
		else
			checkThreshold(item, ctx);
	}

	/**
	 * Check circuit-breaker failure threshold of Endpoint
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function checkThreshold(item, ctx) {
		if (item.count >= item.opts.minRequestCount) {
			const rate = item.failures / item.count;
			if (rate >= item.opts.threshold)
				circuitOpen(item, ctx);
		}
	}

	/**
	 * Change circuit-breaker status to open
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function circuitOpen(item, ctx) {
		item.state = C.CIRCUIT_OPEN;
		item.ep.state = false;

		if (item.cbTimer) {
			clearTimeout(item.cbTimer);
			item.cbTimer = null;
		}

		item.cbTimer = setTimeout(() => circuitHalfOpen(item, ctx), item.opts.halfOpenTime);
		item.cbTimer.unref();

		const rate = item.count > 0 ? item.failures / item.count : 0;
		logger.debug(`Circuit breaker has been opened on '${item.ep.name}' endpoint.`, { nodeID: item.ep.id, action: item.ep.action.name, failures: item.failures, count: item.count, rate });
		broker.broadcast("$circuit-breaker.opened", { nodeID: item.ep.id, action: item.ep.action.name, failures: item.failures, count: item.count, rate });
	}

	/**
	 * Change circuit-breaker status to half-open
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function circuitHalfOpen(item, ctx) {
		item.state = C.CIRCUIT_HALF_OPEN;
		item.ep.state = true;

		logger.debug(`Circuit breaker has been half-opened on '${item.ep.name}' endpoint.`, { nodeID: item.ep.id, action: item.ep.action.name });

		broker.broadcast("$circuit-breaker.half-opened", { nodeID: item.ep.id, action: item.ep.action.name });

		if (item.cbTimer) {
			clearTimeout(item.cbTimer);
			item.cbTimer = null;
		}
	}

	/**
	 * Change circuit-breaker status to half-open waiting. First request is invoked after half-open.
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	*/
	function circuitHalfOpenWait(item, ctx) {
		item.state = C.CIRCUIT_HALF_OPEN_WAIT;
		item.ep.state = false;

		// Anti-stick protection
		item.cbTimer = setTimeout(() => circuitHalfOpen(item, ctx), item.opts.halfOpenTime);
		item.cbTimer.unref();
	}

	/**
	 * Change circuit-breaker status to close
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function circuitClose(item, ctx) {
		item.state = C.CIRCUIT_CLOSE;
		item.ep.state = true;
		item.failures = 0;
		item.count = 0;

		logger.debug(`Circuit breaker has been closed on '${item.ep.name}' endpoint.`, { nodeID: item.ep.id, action: item.ep.action.name });

		broker.broadcast("$circuit-breaker.closed", { nodeID: item.ep.id, action: item.ep.action.name });

		if (item.cbTimer) {
			clearTimeout(item.cbTimer);
			item.cbTimer = null;
		}
	}

	/**
	 * Middleware wrapper function
	 *
	 * @param {Function} handler
	 * @param {Action} action
	 * @returns {Function}
	 */
	function wrapCBMiddleware(handler, action) {
		// Merge action option and broker options
		const opts = Object.assign({}, this.options.circuitBreaker || {}, action.circuitBreaker || {});
		if (opts.enabled) {
			return function circuitBreakerMiddleware(ctx) {
				// Get endpoint state item
				const ep = ctx.endpoint;
				const item = getEpState(ep, opts);

				// Handle half-open state in circuit breaker
				if (item.state == C.CIRCUIT_HALF_OPEN) {
					circuitHalfOpenWait(item, ctx);
				}

				// Call the handler
				return handler(ctx).then(res => {
					const item = getEpState(ep, opts);
					success(item, ctx);

					return res;
				}).catch(err => {
					if (opts.check && opts.check(err)) {
						// Failure if error is created locally (not came from a 3rd node error)
						if (item && (!err.nodeID || err.nodeID == ctx.nodeID)) {
							const item = getEpState(ep, opts);
							failure(item, err, ctx);
						}
					}

					return this.Promise.reject(err);
				});
			}.bind(this);
		}

		return handler;
	}

	return {
		created(_broker) {
			broker = _broker;
			logger = _broker.getLogger("circuit-breaker");

			const opts = broker.options.circuitBreaker;
			if (opts.enabled)
				createWindowTimer(opts.windowTime);
		},

		localAction: wrapCBMiddleware,
		remoteAction: wrapCBMiddleware,

		stopped() {
			if (windowTimer) {
				clearInterval(windowTimer);
			}

		}
	};
};
<commit_msg>renamew circuit breaker methods<commit_after>/*
 * moleculer
 * Copyright (c) 2018 MoleculerJS (https://github.com/moleculerjs/moleculer)
 * MIT Licensed
 */

"use strict";

const C = require("../constants");

module.exports = function() {

	let broker;
	let windowTimer;
	const store = new Map();
	let logger;

	/**
	 * Create timer to clear endpoint store
	 *
	 * @param {Number} windowTime
	 */
	function createWindowTimer(windowTime) {
		if (!windowTimer) {
			windowTimer = setInterval(() => resetStore(), (windowTime || 60) * 1000);
			windowTimer.unref();
		}
	}

	/**
	 * Clear endpoint state store
	 */
	function resetStore() {
		if (!logger) return;

		logger.debug("Reset circuit-breaker endpoint states...");
		store.forEach((item, key) => {
			if (item.count == 0) {
				logger.debug(`Remove '${key}' endpoint state because it is not used`);
				store.delete(key);
				return;
			}

			logger.debug(`Clean '${key}' endpoint state.`);
			item.count = 0;
			item.failures = 0;
		});
	}

	/**
	 * Get Endpoint state from store. If not exists, create it.
	 *
	 * @param {Endpoint} ep
	 * @param {Object} opts
	 * @returns {Object}
	 */
	function getEpState(ep, opts) {
		let item = store.get(ep.name);
		if (!item) {
			item = {
				ep,
				opts,
				count: 0,
				failures: 0,
				state: C.CIRCUIT_CLOSE,
				cbTimer: null
			};
			store.set(ep.name, item);
		}
		return item;
	}

	/**
	 * Increment failure counter
	 *
	 * @param {Object} item
	 * @param {Error} err
	 * @param {Context} ctx
	 */
	function failure(item, err, ctx) {
		item.count++;
		item.failures++;

		checkThreshold(item, ctx);
	}

	/**
	 * Increment request counter and switch CB to CLOSE if it is on HALF_OPEN_WAIT.
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function success(item, ctx) {
		item.count++;

		if (item.state === C.CIRCUIT_HALF_OPEN_WAIT)
			circuitClose(item, ctx);
		else
			checkThreshold(item, ctx);
	}

	/**
	 * Check circuit-breaker failure threshold of Endpoint
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function checkThreshold(item, ctx) {
		if (item.count >= item.opts.minRequestCount) {
			const rate = item.failures / item.count;
			if (rate >= item.opts.threshold)
				trip(item, ctx);
		}
	}

	/**
	 * Trip the circuit-breaker, change the status to open
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function trip(item, ctx) {
		item.state = C.CIRCUIT_OPEN;
		item.ep.state = false;

		if (item.cbTimer) {
			clearTimeout(item.cbTimer);
			item.cbTimer = null;
		}

		item.cbTimer = setTimeout(() => halfOpen(item, ctx), item.opts.halfOpenTime);
		item.cbTimer.unref();

		const rate = item.count > 0 ? item.failures / item.count : 0;
		logger.debug(`Circuit breaker has been opened on '${item.ep.name}' endpoint.`, { nodeID: item.ep.id, action: item.ep.action.name, failures: item.failures, count: item.count, rate });
		broker.broadcast("$circuit-breaker.opened", { nodeID: item.ep.id, action: item.ep.action.name, failures: item.failures, count: item.count, rate });
	}

	/**
	 * Change circuit-breaker status to half-open
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function halfOpen(item, ctx) {
		item.state = C.CIRCUIT_HALF_OPEN;
		item.ep.state = true;

		logger.debug(`Circuit breaker has been half-opened on '${item.ep.name}' endpoint.`, { nodeID: item.ep.id, action: item.ep.action.name });

		broker.broadcast("$circuit-breaker.half-opened", { nodeID: item.ep.id, action: item.ep.action.name });

		if (item.cbTimer) {
			clearTimeout(item.cbTimer);
			item.cbTimer = null;
		}
	}

	/**
	 * Change circuit-breaker status to half-open waiting. First request is invoked after half-open.
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	*/
	function halfOpenWait(item, ctx) {
		item.state = C.CIRCUIT_HALF_OPEN_WAIT;
		item.ep.state = false;

		// Anti-stick protection
		item.cbTimer = setTimeout(() => halfOpen(item, ctx), item.opts.halfOpenTime);
		item.cbTimer.unref();
	}

	/**
	 * Change circuit-breaker status to close
	 *
	 * @param {Object} item
	 * @param {Context} ctx
	 */
	function circuitClose(item, ctx) {
		item.state = C.CIRCUIT_CLOSE;
		item.ep.state = true;
		item.failures = 0;
		item.count = 0;

		logger.debug(`Circuit breaker has been closed on '${item.ep.name}' endpoint.`, { nodeID: item.ep.id, action: item.ep.action.name });

		broker.broadcast("$circuit-breaker.closed", { nodeID: item.ep.id, action: item.ep.action.name });

		if (item.cbTimer) {
			clearTimeout(item.cbTimer);
			item.cbTimer = null;
		}
	}

	/**
	 * Middleware wrapper function
	 *
	 * @param {Function} handler
	 * @param {Action} action
	 * @returns {Function}
	 */
	function wrapCBMiddleware(handler, action) {
		// Merge action option and broker options
		const opts = Object.assign({}, this.options.circuitBreaker || {}, action.circuitBreaker || {});
		if (opts.enabled) {
			return function circuitBreakerMiddleware(ctx) {
				// Get endpoint state item
				const ep = ctx.endpoint;
				const item = getEpState(ep, opts);

				// Handle half-open state in circuit breaker
				if (item.state == C.CIRCUIT_HALF_OPEN) {
					halfOpenWait(item, ctx);
				}

				// Call the handler
				return handler(ctx).then(res => {
					const item = getEpState(ep, opts);
					success(item, ctx);

					return res;
				}).catch(err => {
					if (opts.check && opts.check(err)) {
						// Failure if error is created locally (not came from a 3rd node error)
						if (item && (!err.nodeID || err.nodeID == ctx.nodeID)) {
							const item = getEpState(ep, opts);
							failure(item, err, ctx);
						}
					}

					return this.Promise.reject(err);
				});
			}.bind(this);
		}

		return handler;
	}

	return {
		created(_broker) {
			broker = _broker;
			logger = _broker.getLogger("circuit-breaker");

			const opts = broker.options.circuitBreaker;
			if (opts.enabled)
				createWindowTimer(opts.windowTime);
		},

		localAction: wrapCBMiddleware,
		remoteAction: wrapCBMiddleware,

		stopped() {
			if (windowTimer) {
				clearInterval(windowTimer);
			}

		}
	};
};
<|endoftext|>


<commit_before>import callApp from '../callApp';
import {getValue} from '../../system/system';

export default function senditems(invIdAry) {
  return callApp({
    cmd: 'trade',
    subcmd: 'senditems',
    xc: window.ajaxXC,
    target_username: getValue('itemRecipient'),
    sendItemList: invIdAry // This isn't working...
  });
}
<commit_msg>correct API for app/senditems<commit_after>import callApp from '../callApp';
import getValue from '../../system/getValue';

export default function senditems(invIdAry) {
  return callApp({
    cmd: 'trade',
    subcmd: 'senditems',
    xc: window.ajaxXC,
    target_username: getValue('itemRecipient'),
    items: invIdAry
  });
}
<|endoftext|>


<commit_before>const { Command } = require('discord-akairo');
const moment = require('moment');

function exec(message, args) {
    const color = this.client.color(message);
    const embed = this.client.util.embed().setColor(color);

    if (args.guild.iconURL) embed.setThumbnail(args.guild.iconURL.replace('.jpg', '.png?size=1024'));

    const fields = [
        [
            'Guild Information',
            [
                `**Name**: ${args.guild.name}`,
                `**Guild ID**: ${args.guild.id}`,
                `**Verification**: ${['None', 'Low', 'Medium', '(╯°□°）╯︵ ┻━┻'][args.guild.verificationLevel]}`
            ],
            true
        ],
        [
            'Guild Counts',
            [
                `**Members**: ${args.guild.memberCount}`,
                `**Channels**: ${args.guild.channels.size}`,
                `**Emojis**: ${args.guild.emojis.size}`
            ],
            true
        ],
        [
            'Guild Membership',
            [
                `**Joined At**: ${moment(args.guild.joinedAt).utc().format('dddd, MMMM Do YYYY, h:mm:ss a')}`,
                `**Created At**: ${moment(args.guild.createdAt).utc().format('dddd, MMMM Do YYYY, h:mm:ss a')}`,
                `**Roles**: ${(() => {
                    if ((message.guild && message.guild.id) !== args.guild.id) return 'Outside of guild, cannot view roles.';
                    const roles = args.guild.roles.map(r => r.toString()).join(', ');
                    if (roles.length > 1024) return 'A lot of roles!';
                    return roles;
                })()}`
            ]
        ]
    ];

    for (const field of fields) embed.addField(...field);
    return message.edit({ embed });
}

module.exports = new Command('guild', exec, {
    aliases: ['guild', 'server'],
    args: [
        {
            id: 'guild',
            type: 'guild',
            default: m => m.guild || m.client.guilds.random()
        }
    ],
    clientPermissions: ['EMBED_LINKS'],
    category: 'info'
});
<commit_msg>Delete guild.js<commit_after><|endoftext|>


<commit_before>// Write a program that iterates the integers from 1 to 100, printing the numbers to the screen.
// For each number that is a multiple of 3, however, print "Fizz" instead of the number.
// For multiples of 5 print "Buzz" instead of the number.
// For numbers that are multiples of both print "FizzBuzz."

function fizzBuzz() { // 95 ms runtime
    var res = "";
    var resStr = ""
    for (var i = 1; i < 100; i++) {
        res = "";
        if (i % 3 == 0) { res = "Fizz"; }
        if (i % 5 == 0) { res += "Buzz"; }
        if (!res) { res = i; }
        resStr += res + " ";
    }
    return resStr;
}

// -----------------------------------------------

var fizzBuzz = function(n) { // 89 ms runtime
    var result = [],
        str, i=1;
    while( i <= n ){
        str = "";
        if( i%3===0 ) str = 'Fizz';
        if( i%5===0 ) str += 'Buzz';
        if(!str) str += i;
        result.push( str );
        i++;
    }
    return result;
};
<commit_msg>add params ofr second solution<commit_after>// Write a program that iterates the integers from 1 to 100, printing the numbers to the screen.
// For each number that is a multiple of 3, however, print "Fizz" instead of the number.
// For multiples of 5 print "Buzz" instead of the number.
// For numbers that are multiples of both print "FizzBuzz."

function fizzBuzz() { // 95 ms runtime
    var res = "";
    var resStr = ""
    for (var i = 1; i < 100; i++) {
        res = "";
        if (i % 3 == 0) { res = "Fizz"; }
        if (i % 5 == 0) { res += "Buzz"; }
        if (!res) { res = i; }
        resStr += res + " ";
    }
    return resStr;
}

// -----------------------------------------------

/**
 * @param {number} n
 * @return {string[]}
 */

var fizzBuzz = function(n) { // 89 ms runtime
    var result = [],
        str, i=1;
    while( i <= n ){
        str = "";
        if( i%3===0 ) str = 'Fizz';
        if( i%5===0 ) str += 'Buzz';
        if(!str) str += i;
        result.push( str );
        i++;
    }
    return result;
};
<|endoftext|>


<commit_before>// Write a program that iterates the integers from 1 to 100, printing the numbers to the screen.
// For each number that is a multiple of 3, however, print "Fizz" instead of the number.
// For multiples of 5 print "Buzz" instead of the number.
// For numbers that are multiples of both print "FizzBuzz."

function fizzBuzz() {
    var res = "";
    var resStr = ""
    for (var i = 1; i < 100; i++) {
        res = "";
        if (i % 3 == 0) { res = "Fizz"; }
        if (i % 5 == 0) { res += "Buzz"; }
        if (!res) { res = i; }
        resStr += res + " ";
    }
    return resStr;
}

// -----------------------------------------------

var fizzBuzz = function(n) {
    var result = [];
    for( var i=1; i<=n; i++ ){
        if( i%3===0 && i%5===0 ){
            result.push( 'FizzBuzz' );
        } else if( i%3===0 ){
            result.push( 'Fizz' );
        } else if( i%5===0 ){
            result.push( 'Buzz' );
        } else {
            result.push( ""+i );
        }
    }
    return result;
};
<commit_msg>add notes<commit_after>// Write a program that iterates the integers from 1 to 100, printing the numbers to the screen.
// For each number that is a multiple of 3, however, print "Fizz" instead of the number.
// For multiples of 5 print "Buzz" instead of the number.
// For numbers that are multiples of both print "FizzBuzz."

function fizzBuzz() { // 95 ms runtime
    var res = "";
    var resStr = ""
    for (var i = 1; i < 100; i++) {
        res = "";
        if (i % 3 == 0) { res = "Fizz"; }
        if (i % 5 == 0) { res += "Buzz"; }
        if (!res) { res = i; }
        resStr += res + " ";
    }
    return resStr;
}

// -----------------------------------------------

var fizzBuzz = function(n) { // 156 ms
    var result = [];
    for( var i=1; i<=n; i++ ){
        if( i%3===0 && i%5===0 ){
            result.push( 'FizzBuzz' );
        } else if( i%3===0 ){
            result.push( 'Fizz' );
        } else if( i%5===0 ){
            result.push( 'Buzz' );
        } else {
            result.push( ""+i );
        }
    }
    return result;
};
<|endoftext|>


<commit_before>/* @flow */
/* eslint dot-notation: 0*/
import { config, bus, Constants, cache } from '../../core-server';
import Counter from '../../lib/counter';
import log from 'winston';
import values from 'lodash/values';
import request from 'request';
import { getTokenFromSession, updateUser } from './handleUpstreamMessage';
const authKey = 'key=' + config.gcm.apiKey;
const options = {
	url: 'https://iid.googleapis.com/iid/v1:batchAdd',
	json: true,
	method: 'POST',
	headers: {
		Authorization: authKey
	},
	body: {}
};

export function getIIDInfo(iid: String, cb: Function) {
	request({
		url: `https://iid.googleapis.com/iid/info/${iid}?details=true`,
		method: 'GET',
		headers: {
			Authorization: authKey
		},
	}, cb);
}

function unsubscribeTopics (data, cb) {
	const iid = data.iid;

	if (data.topic) {
		request({
			...options,
			url: 'https://iid.googleapis.com/iid/v1:batchRemove',
			body: {
				registration_tokens: [ iid ],
				to: '/topics/' + data.topic
			}
		}, (err, rspns, bdy) => {
			if (!err) {
				log.info('unsubscribed from ', data.topic || '');
				log.info(bdy);
			} else {
				log.error(err);
			}
		});
	} else {
		getIIDInfo(iid, async (e, r, b) => {
			if (e) {
				log.error(e);
				return;
			}
			try {
				// unsubscribe thread topics
				await Object.keys(JSON.parse(b).rel.topics).map(topic => {
					if (!/thread-/.test(topic)) {
						log.debug('does not match thread');
						return null;
					}

					return new Promise((resolve, reject) => {
						request({
							...options,
							url: 'https://iid.googleapis.com/iid/v1:batchRemove',
							body: {
								registration_tokens: [ iid ],
								to: '/topics/' + topic
							}
						}, (err, rspns, bdy) => {
							if (!err) {
								log.info('unsubscribed from ', topic);
								log.info(bdy);
								resolve();
							} else {
								log.error(err);
								reject(err);
							}
						});
					});
				});
			} catch (err) {
				// ignore
			}
			cb();
		});
	}

}

export function subscribe (userRel: Object) {
	const gcm = userRel.params.gcm;
	const userName = userRel.params['facebook'].name || userRel.params['google'].name;
	function register () {
		const	tokens = values(gcm);

		log.info('tokens: ', tokens);
		tokens.forEach(token => {
			request({
				...options,
				body: {
					registration_tokens: [ token ],
					to: '/topics/' + userRel.topic
				}
			}, (error, response, body) => {
				if (error) {
					log.error('error subscribing to topic: ', userRel.topic, token, error);
					if (error.type === 'TOO_MANY_TOPICS') {
						log.info('unsubscribe few old topics');
						unsubscribeTopics({ iid: token }, () => {
							subscribe(userRel);
						});
					} else {
						log.error('can not subscribe to topic', error);
					}
				}
				if (body.error) {
					log.error(body, userRel.topic);
					// console.log(options);
				} else {
					log.info(userName, 'succefully subscribed to: ' + userRel.topic, body);
					// getIIDInfo(token, (e, r, b) => {
					// 	log.info(b);
					// 	// return;
					// });
				}
			});
		});
	}
	if (!gcm) {
		log.debug('No gcm found for user retrying from saved token...');
		const data = getTokenFromSession();
		if (data.error) log.info(data.error);
		updateUser({ data }, (error) => {
			// console.log("dta: ", data);
			if (!error) {
				register();
				return;
			} else {
				log.info('No gcm found for user');
			}
		});
	} else {
		register();
	}

}
function handleSubscription(changes, next) {
	const counter = new Counter();

	if (!changes.entities || !config.gcm.apiKey) {
		next();
		return;
	}
	// console.log("chandra: ", changes);
	for (const i in changes.entities) {
		const entity = changes.entities[i];

		if (
				entity.type === Constants.TYPE_THREADREL ||
				entity.type === Constants.TYPE_ROOMREL
			) {
			// console.log("ksdfhjhadf : ", entity);
			if (!entity.createTime || entity.createTime !== entity.updateTime) {
				log.info('Not created now, return', entity);
				continue;
			}
			let user = changes.entities[entity.user];

			if (!user) {
				counter.inc();
				cache.getEntity(entity.user, (e, u) => {
					user = u;
					counter.dec();
				});
			}
			counter.then(() => {
				if (
					entity.roles && entity.roles.length === 0 ||
					entity.roles.indexOf(Constants.ROLE_FOLLOWER) === -1 &&
					entity.roles.indexOf(Constants.ROLE_CREATOR) === -1
				) {
					// log.info('Got unfollow, unsubscribe from topics');
					// const gcm = user.params && user.params.gcm;
					// const	tokens = values(gcm);
					// const topic = entity.type === Constants.TYPE_ROOMREL ? 'room-' +
					//  entity.item : 'thread-' + entity.item;
					// tokens.forEach((token) => {
					// 	unsubscribeTopics({ iid: token, topic }, () => {
					// 		log.info('Unsubscribed from topic: ', topic);
					// 	});
					// });
					// console.log("sdjfh jsghf gh fdgfm: ", Constants.ROLE_OWNER, entity.roles.indexOf(Constants.ROLE_OWNER), entity);
					return;
				} else if (entity.roles && entity.roles.length > 0) {
					// console.log("jhgf shfg: ", entity)
					log.info('subscribe ' + user.id + ' to ' + entity.item);
					subscribe({
						params: user.params || {},
						topic: entity.type === Constants.TYPE_ROOMREL ? 'room-' + entity.item :
						'thread-' + entity.item
					});
				}
			});
		}
	}
	next();
}

// console.log("Constants.APP_PRIORITIES.GCM", Constants.APP_PRIORITIES.GCM);
bus.on('change', handleSubscription, Constants.APP_PRIORITIES.GCM);
<commit_msg>Fix: check for facebook tag in user params<commit_after>/* @flow */
/* eslint dot-notation: 0*/
import { config, bus, Constants, cache } from '../../core-server';
import Counter from '../../lib/counter';
import log from 'winston';
import values from 'lodash/values';
import request from 'request';
import { getTokenFromSession, updateUser } from './handleUpstreamMessage';
const authKey = 'key=' + config.gcm.apiKey;
const options = {
	url: 'https://iid.googleapis.com/iid/v1:batchAdd',
	json: true,
	method: 'POST',
	headers: {
		Authorization: authKey
	},
	body: {}
};

export function getIIDInfo(iid: String, cb: Function) {
	request({
		url: `https://iid.googleapis.com/iid/info/${iid}?details=true`,
		method: 'GET',
		headers: {
			Authorization: authKey
		},
	}, cb);
}

function unsubscribeTopics (data, cb) {
	const iid = data.iid;

	if (data.topic) {
		request({
			...options,
			url: 'https://iid.googleapis.com/iid/v1:batchRemove',
			body: {
				registration_tokens: [ iid ],
				to: '/topics/' + data.topic
			}
		}, (err, rspns, bdy) => {
			if (!err) {
				log.info('unsubscribed from ', data.topic || '');
				log.info(bdy);
			} else {
				log.error(err);
			}
		});
	} else {
		getIIDInfo(iid, async (e, r, b) => {
			if (e) {
				log.error(e);
				return;
			}
			try {
				// unsubscribe thread topics
				await Object.keys(JSON.parse(b).rel.topics).map(topic => {
					if (!/thread-/.test(topic)) {
						log.debug('does not match thread');
						return null;
					}

					return new Promise((resolve, reject) => {
						request({
							...options,
							url: 'https://iid.googleapis.com/iid/v1:batchRemove',
							body: {
								registration_tokens: [ iid ],
								to: '/topics/' + topic
							}
						}, (err, rspns, bdy) => {
							if (!err) {
								log.info('unsubscribed from ', topic);
								log.info(bdy);
								resolve();
							} else {
								log.error(err);
								reject(err);
							}
						});
					});
				});
			} catch (err) {
				// ignore
			}
			cb();
		});
	}

}

export function subscribe (userRel: Object) {
	const gcm = userRel.params.gcm;
	const userName = userRel.params['facebook'] ? userRel.params['facebook'].name : userRel.params['google'].name;
	function register () {
		const	tokens = values(gcm);

		log.info('tokens: ', tokens);
		tokens.forEach(token => {
			request({
				...options,
				body: {
					registration_tokens: [ token ],
					to: '/topics/' + userRel.topic
				}
			}, (error, response, body) => {
				if (error) {
					log.error('error subscribing to topic: ', userRel.topic, token, error);
					if (error.type === 'TOO_MANY_TOPICS') {
						log.info('unsubscribe few old topics');
						unsubscribeTopics({ iid: token }, () => {
							subscribe(userRel);
						});
					} else {
						log.error('can not subscribe to topic', error);
					}
				}
				if (body.error) {
					log.error(body, userRel.topic);
					// console.log(options);
				} else {
					log.info(userName, 'succefully subscribed to: ' + userRel.topic, body);
					// getIIDInfo(token, (e, r, b) => {
					// 	log.info(b);
					// 	// return;
					// });
				}
			});
		});
	}
	if (!gcm) {
		log.debug('No gcm found for user retrying from saved token...');
		const data = getTokenFromSession();
		if (data.error) log.info(data.error);
		updateUser({ data }, (error) => {
			// console.log("dta: ", data);
			if (!error) {
				register();
				return;
			} else {
				log.info('No gcm found for user');
			}
		});
	} else {
		register();
	}

}
function handleSubscription(changes, next) {
	const counter = new Counter();

	if (!changes.entities || !config.gcm.apiKey) {
		next();
		return;
	}
	// console.log("chandra: ", changes);
	for (const i in changes.entities) {
		const entity = changes.entities[i];

		if (
				entity.type === Constants.TYPE_THREADREL ||
				entity.type === Constants.TYPE_ROOMREL
			) {
			// console.log("ksdfhjhadf : ", entity);
			if (!entity.createTime || entity.createTime !== entity.updateTime) {
				log.info('Not created now, return', entity);
				continue;
			}
			let user = changes.entities[entity.user];

			if (!user) {
				counter.inc();
				cache.getEntity(entity.user, (e, u) => {
					user = u;
					counter.dec();
				});
			}
			counter.then(() => {
				if (
					entity.roles && entity.roles.length === 0 ||
					entity.roles.indexOf(Constants.ROLE_FOLLOWER) === -1 &&
					entity.roles.indexOf(Constants.ROLE_CREATOR) === -1
				) {
					// log.info('Got unfollow, unsubscribe from topics');
					// const gcm = user.params && user.params.gcm;
					// const	tokens = values(gcm);
					// const topic = entity.type === Constants.TYPE_ROOMREL ? 'room-' +
					//  entity.item : 'thread-' + entity.item;
					// tokens.forEach((token) => {
					// 	unsubscribeTopics({ iid: token, topic }, () => {
					// 		log.info('Unsubscribed from topic: ', topic);
					// 	});
					// });
					// console.log("sdjfh jsghf gh fdgfm: ", Constants.ROLE_OWNER, entity.roles.indexOf(Constants.ROLE_OWNER), entity);
					return;
				} else if (entity.roles && entity.roles.length > 0) {
					// console.log("jhgf shfg: ", entity)
					log.info('subscribe ' + user.id + ' to ' + entity.item);
					subscribe({
						params: user.params || {},
						topic: entity.type === Constants.TYPE_ROOMREL ? 'room-' + entity.item :
						'thread-' + entity.item
					});
				}
			});
		}
	}
	next();
}

// console.log("Constants.APP_PRIORITIES.GCM", Constants.APP_PRIORITIES.GCM);
bus.on('change', handleSubscription, Constants.APP_PRIORITIES.GCM);
<|endoftext|>


<commit_before>;

import angular from 'angular';
import squareImageModule from '../components/square-image';
import { labels } from '../won-label-utils';
import {attach} from '../utils.js';
import { actionCreators }  from '../actions/actions';

const serviceDependencies = ['$q', '$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                    <won-square-image src="request.titleImgSrc" title="self.item.remoteNeed.title"></won-square-image>

{{self.item.remoteNeed.title}}

{{self.item.connection.timestamp}}

                                {{self.item.group}} –

                            {{self.wonLabels.type[self.item.remoteNeed.basicNeedType]}}

                            {{self.item.lastEvent.msg}}

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);
            window.needconnmsg = this;
            this.wonLabels = labels;
            /*            const selectFromState = (state)=>{

             return {
             unreadUris: state.getIn(['events','unreadEventUris'])
             };
             }
             this.wonLabels = labels;

             const disconnect = this.$ngRedux.connect(selectFromState,actionCreators)(this);
             //  this.loadMatches();
             this.$scope.$on('$destroy', disconnect);*/
        }

        /*        read(request){
         if(!this.unreadUris.has(request.connection.uri)){
         return true
         }
         return false;
         }*/
        /*        toggleRequest() {
         this.open = !this.open;
         }
         */

        openMessage(item) {
            //this.events__read(item)
            this.openConversation = item;
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {item: "=",
                open: "=",
                openConversation: "="},
        template: template
    }

}

export default angular.module('won.owner.components.needConnectionMessageLine', [])
    .directive('wonConnectionMessageItemLine', genComponentConf)
    .name;

<commit_msg>removed unnecessary comments and code<commit_after>;

import won from '../won-es6';
import angular from 'angular';
import squareImageModule from '../components/square-image';
import { labels } from '../won-label-utils';
import { attach } from '../utils.js';
import { actionCreators }  from '../actions/actions';

const serviceDependencies = ['$q', '$ngRedux', '$scope'];
function genComponentConf() {
    let template = `

                    <won-square-image src="request.titleImgSrc" title="self.item.remoteNeed.title"></won-square-image>

{{self.item.remoteNeed.title}}

{{self.item.connection.timestamp}}

                                {{self.item.group}} –

                            {{self.wonLabels.type[self.item.remoteNeed.basicNeedType]}}

                            {{self.item.lastEvent.msg}}

    `;

    class Controller {
        constructor() {
            attach(this, serviceDependencies, arguments);
            window.needconnmsg = this;
            this.wonLabels = labels;
        }

        openMessage(item) {
            //this.events__read(item)
            this.openConversation = item;
        }
    }
    Controller.$inject = serviceDependencies;
    return {
        restrict: 'E',
        controller: Controller,
        controllerAs: 'self',
        bindToController: true, //scope-bindings -> ctrl
        scope: {item: "=",
                open: "=",
                openConversation: "="},
        template: template
    }

}

export default angular.module('won.owner.components.needConnectionMessageLine', [])
    .directive('wonConnectionMessageItemLine', genComponentConf)
    .name;

<|endoftext|>


<commit_before>var log4js = require('log4js');
var settings = require('../../utils/Settings');
var socketIORouter = require("../../handler/SocketIORouter");
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");

// there shouldn't be a browser that isn't compatible to all
// transports in this list at once
// e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling

var socketio = require('socket.io')({
  transports: settings.socketTransportProtocols
});

var padMessageHandler = require("../../handler/PadMessageHandler");

var connect = require('connect');

exports.expressCreateServer = function (hook_name, args, cb) {
  //init socket.io and redirect all requests to the MessageHandler
  var io = socketio.listen(args.server);

  /* Require an express session cookie to be present, and load the
   * session. See http://www.danielbaulig.de/socket-ioexpress for more
   * info */

  io.use(function(socket, accept) {
    var data = socket.request;
    if (!data.headers.cookie) return accept('No session cookie transmitted.', false);

    // Use connect's cookie parser, because it knows how to parse signed cookies
    connect.cookieParser(webaccess.secret)(data, {}, function(err){
      if(err) {
        console.error(err);
        accept("Couldn't parse request cookies. ", false);
        return;
      }

      data.sessionID = data.signedCookies.express_sid;
      args.app.sessionStore.get(data.sessionID, function (err, session) {
        if (err || !session) return accept('Bad session / session has expired', false);
        data.session = new connect.middleware.session.Session(data, session);
        accept(null, true);
      });
    });
  });

  // var socketIOLogger = log4js.getLogger("socket.io");
  // Debug logging now has to be set at an environment level, this is stupid.
  // https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0
  // This debug logging environment is set in Settings.js

  //minify socket.io javascript
  // Due to a shitty decision by the SocketIO team minification is
  // no longer available, details available at:
  // http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0
  // if(settings.minify) io.enable('browser client minification');

  //Initalize the Socket.IO Router
  socketIORouter.setSocketIO(io);
  socketIORouter.addComponent("pad", padMessageHandler);

  hooks.callAll("socketio", {"app": args.app, "io": io, "server": args.server});
}
<commit_msg>really recreate socketio-client in expressCreateServer, fixes #2342<commit_after>var log4js = require('log4js');
var settings = require('../../utils/Settings');
var socketio = require('socket.io');
var socketIORouter = require("../../handler/SocketIORouter");
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");

var padMessageHandler = require("../../handler/PadMessageHandler");

var connect = require('connect');

exports.expressCreateServer = function (hook_name, args, cb) {
  //init socket.io and redirect all requests to the MessageHandler
  // there shouldn't be a browser that isn't compatible to all
  // transports in this list at once
  // e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling
  var io = socketio({
    transports: settings.socketTransportProtocols
  }).listen(args.server);

  /* Require an express session cookie to be present, and load the
   * session. See http://www.danielbaulig.de/socket-ioexpress for more
   * info */

  io.use(function(socket, accept) {
    var data = socket.request;
    if (!data.headers.cookie) return accept('No session cookie transmitted.', false);

    // Use connect's cookie parser, because it knows how to parse signed cookies
    connect.cookieParser(webaccess.secret)(data, {}, function(err){
      if(err) {
        console.error(err);
        accept("Couldn't parse request cookies. ", false);
        return;
      }

      data.sessionID = data.signedCookies.express_sid;
      args.app.sessionStore.get(data.sessionID, function (err, session) {
        if (err || !session) return accept('Bad session / session has expired', false);
        data.session = new connect.middleware.session.Session(data, session);
        accept(null, true);
      });
    });
  });

  // var socketIOLogger = log4js.getLogger("socket.io");
  // Debug logging now has to be set at an environment level, this is stupid.
  // https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0
  // This debug logging environment is set in Settings.js

  //minify socket.io javascript
  // Due to a shitty decision by the SocketIO team minification is
  // no longer available, details available at:
  // http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0
  // if(settings.minify) io.enable('browser client minification');

  //Initalize the Socket.IO Router
  socketIORouter.setSocketIO(io);
  socketIORouter.addComponent("pad", padMessageHandler);

  hooks.callAll("socketio", {"app": args.app, "io": io, "server": args.server});
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * 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 Google Inc. 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
 * OWNER OR CONTRIBUTORS 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.
 *
 */

'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var grpc = require('..');
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
var GoogleAuth = require('google-auth-library');

var assert = require('assert');

var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' +
    '@developer.gserviceaccount.com');
var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
    '@developer.gserviceaccount.com');

/**
 * Create a buffer filled with size zeroes
 * @param {number} size The length of the buffer
 * @return {Buffer} The new buffer
 */
function zeroBuffer(size) {
  var zeros = new Buffer(size);
  zeros.fill(0);
  return zeros;
}

/**
 * Run the empty_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyUnary(client, done) {
  var call = client.emptyCall({}, function(err, resp) {
    assert.ifError(err);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the large_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function largeUnary(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_size: 314159,
    payload: {
      body: zeroBuffer(271828)
    }
  };
  var call = client.unaryCall(arg, function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
    assert.strictEqual(resp.payload.body.length, 314159);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the client_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function clientStreaming(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.aggregated_payload_size, 74922);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var payload_sizes = [27182, 8, 1828, 45904];
  for (var i = 0; i < payload_sizes.length; i++) {
    call.write({payload: {body: zeroBuffer(payload_sizes[i])}});
  }
  call.end();
}

/**
 * Run the server_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function serverStreaming(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_parameters: [
      {size: 31415},
      {size: 9},
      {size: 2653},
      {size: 58979}
    ]
  };
  var call = client.streamingOutputCall(arg);
  var resp_index = 0;
  call.on('data', function(value) {
    assert(resp_index < 4);
    assert.strictEqual(value.payload.type, 'COMPRESSABLE');
    assert.strictEqual(value.payload.body.length,
                       arg.response_parameters[resp_index].size);
    resp_index += 1;
  });
  call.on('end', function() {
    assert.strictEqual(resp_index, 4);
    if (done) {
      done();
    }
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
  });
}

/**
 * Run the ping_pong test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function pingPong(client, done) {
  var payload_sizes = [27182, 8, 1828, 45904];
  var response_sizes = [31415, 9, 2653, 58979];
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var index = 0;
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: response_sizes[index]}
      ],
      payload: {body: zeroBuffer(payload_sizes[index])}
  });
  call.on('data', function(response) {
    assert.strictEqual(response.payload.type, 'COMPRESSABLE');
    assert.equal(response.payload.body.length, response_sizes[index]);
    index += 1;
    if (index === 4) {
      call.end();
    } else {
      call.write({
        response_type: 'COMPRESSABLE',
        response_parameters: [
          {size: response_sizes[index]}
        ],
        payload: {body: zeroBuffer(payload_sizes[index])}
      });
    }
  });
}

/**
 * Run the empty_stream test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyStream(client, done) {
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  call.on('data', function(value) {
    assert.fail(value, null, 'No data should have been received', '!==');
  });
  call.end();
}

/**
 * Run the cancel_after_begin test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterBegin(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.strictEqual(err.code, grpc.status.CANCELLED);
    done();
  });
  call.cancel();
}

/**
 * Run the cancel_after_first_response test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterFirstResponse(client, done) {
  var call = client.fullDuplexCall();
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: 31415}
      ],
      payload: {body: zeroBuffer(27182)}
  });
  call.on('data', function(data) {
    call.cancel();
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.CANCELLED);
    done();
  });
}

function timeoutOnSleepingServer(client, done) {
  var deadline = new Date();
  deadline.setMilliseconds(deadline.getMilliseconds() + 1);
  var call = client.fullDuplexCall(null, deadline);
  call.write({
    payload: {body: zeroBuffer(27182)}
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED);
    done();
  });
}

/**
 * Run one of the authentication tests.
 * @param {string} expected_user The expected username in the response
 * @param {Client} client The client to test against
 * @param {?string} scope The scope to apply to the credentials
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function authTest(expected_user, scope, client, done) {
  (new GoogleAuth()).getApplicationDefault(function(err, credential) {
    assert.ifError(err);
    if (credential.createScopedRequired() && scope) {
      credential = credential.createScoped(scope);
    }
    client.updateMetadata = grpc.getGoogleAuthDelegate(credential);
    var arg = {
      response_type: 'COMPRESSABLE',
      response_size: 314159,
      payload: {
        body: zeroBuffer(271828)
      },
      fill_username: true,
      fill_oauth_scope: true
    };
    var call = client.unaryCall(arg, function(err, resp) {
      assert.ifError(err);
      assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
      assert.strictEqual(resp.payload.body.length, 314159);
      assert.strictEqual(resp.username, expected_user);
      assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
    });
    call.on('status', function(status) {
      assert.strictEqual(status.code, grpc.status.OK);
      if (done) {
        done();
      }
    });
  });
}

/**
 * Map from test case names to test functions
 */
var test_cases = {
  empty_unary: emptyUnary,
  large_unary: largeUnary,
  client_streaming: clientStreaming,
  server_streaming: serverStreaming,
  ping_pong: pingPong,
  empty_stream: emptyStream,
  cancel_after_begin: cancelAfterBegin,
  cancel_after_first_response: cancelAfterFirstResponse,
  timeout_on_sleeping_server: timeoutOnSleepingServer,
  compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER, null),
  service_account_creds: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
  jwt_token_creds: _.partial(authTest, AUTH_USER, null)
};

/**
 * Execute a single test case.
 * @param {string} address The address of the server to connect to, in the
 *     format 'hostname:port'
 * @param {string} host_overrirde The hostname of the server to use as an SSL
 *     override
 * @param {string} test_case The name of the test case to run
 * @param {bool} tls Indicates that a secure channel should be used
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function runTest(address, host_override, test_case, tls, test_ca, done) {
  // TODO(mlumish): enable TLS functionality
  var options = {};
  if (tls) {
    var ca_path;
    if (test_ca) {
      ca_path = path.join(__dirname, '../test/data/ca.pem');
    } else {
      ca_path = process.env.SSL_CERT_FILE;
    }
    var ca_data = fs.readFileSync(ca_path);
    var creds = grpc.Credentials.createSsl(ca_data);
    options.credentials = creds;
    if (host_override) {
      options['grpc.ssl_target_name_override'] = host_override;
    }
  }
  var client = new testProto.TestService(address, options);

  test_cases[test_case](client, done);
}

if (require.main === module) {
  var parseArgs = require('minimist');
  var argv = parseArgs(process.argv, {
    string: ['server_host', 'server_host_override', 'server_port', 'test_case',
             'use_tls', 'use_test_ca']
  });
  runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
          argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
          function () {
            console.log('OK:', argv.test_case);
          });
}

/**
 * See docs for runTest
 */
exports.runTest = runTest;
<commit_msg>Added oauth2_auth_token and per_rpc_creds Node interop tests<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * All rights reserved.
 *
 * 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 Google Inc. 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
 * OWNER OR CONTRIBUTORS 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.
 *
 */

'use strict';

var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var grpc = require('..');
var testProto = grpc.load(__dirname + '/test.proto').grpc.testing;
var GoogleAuth = require('google-auth-library');

var assert = require('assert');

var AUTH_SCOPE = 'https://www.googleapis.com/auth/xapi.zoo';
var AUTH_SCOPE_RESPONSE = 'xapi.zoo';
var AUTH_USER = ('155450119199-3psnrh1sdr3d8cpj1v46naggf81mhdnk' +
    '@developer.gserviceaccount.com');
var COMPUTE_ENGINE_USER = ('155450119199-r5aaqa2vqoa9g5mv2m6s3m1l293rlmel' +
    '@developer.gserviceaccount.com');

/**
 * Create a buffer filled with size zeroes
 * @param {number} size The length of the buffer
 * @return {Buffer} The new buffer
 */
function zeroBuffer(size) {
  var zeros = new Buffer(size);
  zeros.fill(0);
  return zeros;
}

/**
 * Run the empty_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyUnary(client, done) {
  var call = client.emptyCall({}, function(err, resp) {
    assert.ifError(err);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the large_unary test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function largeUnary(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_size: 314159,
    payload: {
      body: zeroBuffer(271828)
    }
  };
  var call = client.unaryCall(arg, function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
    assert.strictEqual(resp.payload.body.length, 314159);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
}

/**
 * Run the client_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function clientStreaming(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.ifError(err);
    assert.strictEqual(resp.aggregated_payload_size, 74922);
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var payload_sizes = [27182, 8, 1828, 45904];
  for (var i = 0; i < payload_sizes.length; i++) {
    call.write({payload: {body: zeroBuffer(payload_sizes[i])}});
  }
  call.end();
}

/**
 * Run the server_streaming test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function serverStreaming(client, done) {
  var arg = {
    response_type: 'COMPRESSABLE',
    response_parameters: [
      {size: 31415},
      {size: 9},
      {size: 2653},
      {size: 58979}
    ]
  };
  var call = client.streamingOutputCall(arg);
  var resp_index = 0;
  call.on('data', function(value) {
    assert(resp_index < 4);
    assert.strictEqual(value.payload.type, 'COMPRESSABLE');
    assert.strictEqual(value.payload.body.length,
                       arg.response_parameters[resp_index].size);
    resp_index += 1;
  });
  call.on('end', function() {
    assert.strictEqual(resp_index, 4);
    if (done) {
      done();
    }
  });
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
  });
}

/**
 * Run the ping_pong test
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function pingPong(client, done) {
  var payload_sizes = [27182, 8, 1828, 45904];
  var response_sizes = [31415, 9, 2653, 58979];
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  var index = 0;
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: response_sizes[index]}
      ],
      payload: {body: zeroBuffer(payload_sizes[index])}
  });
  call.on('data', function(response) {
    assert.strictEqual(response.payload.type, 'COMPRESSABLE');
    assert.equal(response.payload.body.length, response_sizes[index]);
    index += 1;
    if (index === 4) {
      call.end();
    } else {
      call.write({
        response_type: 'COMPRESSABLE',
        response_parameters: [
          {size: response_sizes[index]}
        ],
        payload: {body: zeroBuffer(payload_sizes[index])}
      });
    }
  });
}

/**
 * Run the empty_stream test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function emptyStream(client, done) {
  var call = client.fullDuplexCall();
  call.on('status', function(status) {
    assert.strictEqual(status.code, grpc.status.OK);
    if (done) {
      done();
    }
  });
  call.on('data', function(value) {
    assert.fail(value, null, 'No data should have been received', '!==');
  });
  call.end();
}

/**
 * Run the cancel_after_begin test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterBegin(client, done) {
  var call = client.streamingInputCall(function(err, resp) {
    assert.strictEqual(err.code, grpc.status.CANCELLED);
    done();
  });
  call.cancel();
}

/**
 * Run the cancel_after_first_response test.
 * @param {Client} client The client to test against
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function cancelAfterFirstResponse(client, done) {
  var call = client.fullDuplexCall();
  call.write({
      response_type: 'COMPRESSABLE',
      response_parameters: [
        {size: 31415}
      ],
      payload: {body: zeroBuffer(27182)}
  });
  call.on('data', function(data) {
    call.cancel();
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.CANCELLED);
    done();
  });
}

function timeoutOnSleepingServer(client, done) {
  var deadline = new Date();
  deadline.setMilliseconds(deadline.getMilliseconds() + 1);
  var call = client.fullDuplexCall(null, deadline);
  call.write({
    payload: {body: zeroBuffer(27182)}
  });
  call.on('error', function(error) {
    assert.strictEqual(error.code, grpc.status.DEADLINE_EXCEEDED);
    done();
  });
}

/**
 * Run one of the authentication tests.
 * @param {string} expected_user The expected username in the response
 * @param {Client} client The client to test against
 * @param {?string} scope The scope to apply to the credentials
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function authTest(expected_user, scope, client, done) {
  (new GoogleAuth()).getApplicationDefault(function(err, credential) {
    assert.ifError(err);
    if (credential.createScopedRequired() && scope) {
      credential = credential.createScoped(scope);
    }
    client.updateMetadata = grpc.getGoogleAuthDelegate(credential);
    var arg = {
      response_type: 'COMPRESSABLE',
      response_size: 314159,
      payload: {
        body: zeroBuffer(271828)
      },
      fill_username: true,
      fill_oauth_scope: true
    };
    var call = client.unaryCall(arg, function(err, resp) {
      assert.ifError(err);
      assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
      assert.strictEqual(resp.payload.body.length, 314159);
      assert.strictEqual(resp.username, expected_user);
      assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
    });
    call.on('status', function(status) {
      assert.strictEqual(status.code, grpc.status.OK);
      if (done) {
        done();
      }
    });
  });
}

function oauth2Test(expected_user, scope, per_rpc, client, done) {
  (new GoogleAuth()).getApplicationDefault(function(err, credential) {
    assert.ifError(err);
    var arg = {
      response_type: 'COMPRESSABLE',
      response_size: 314159,
      payload: {
        body: zeroBuffer(271828)
      },
      fill_username: true,
      fill_oauth_scope: true
    };
    credential = credential.createScoped(scope);
    credential.getAccessToken(function(err, token) {
      assert.ifError(err);
      var updateMetadata = function(authURI, metadata, callback) {
        metadata = _.clone(metadata);
        if (metadata.Authorization) {
          metadata.Authorization = _.clone(metadata.Authorization);
        } else {
          metadata.Authorization = [];
        }
        metadata.Authorization.push('Bearer ' + token);
        callback(null, metadata);
      };
      var makeTestCall = function(error, client_metadata) {
        assert.ifError(error);
        var call = client.unaryCall(arg, function(err, resp) {
          assert.ifError(err);
          assert.strictEqual(resp.payload.type, 'COMPRESSABLE');
          assert.strictEqual(resp.payload.body.length, 314159);
          assert.strictEqual(resp.username, expected_user);
          assert.strictEqual(resp.oauth_scope, AUTH_SCOPE_RESPONSE);
        });
        call.on('status', function(status) {
          assert.strictEqual(status.code, grpc.status.OK);
          if (done) {
            done();
          }
        });
      };
      if (per_rpc) {
        updateMetadata('', {}, makeTestCall);
      } else {
        client.updateMetadata = updateMetadata;
        makeTestCall(null, {});
      }

    });
  });
}

/**
 * Map from test case names to test functions
 */
var test_cases = {
  empty_unary: emptyUnary,
  large_unary: largeUnary,
  client_streaming: clientStreaming,
  server_streaming: serverStreaming,
  ping_pong: pingPong,
  empty_stream: emptyStream,
  cancel_after_begin: cancelAfterBegin,
  cancel_after_first_response: cancelAfterFirstResponse,
  timeout_on_sleeping_server: timeoutOnSleepingServer,
  compute_engine_creds: _.partial(authTest, COMPUTE_ENGINE_USER, null),
  service_account_creds: _.partial(authTest, AUTH_USER, AUTH_SCOPE),
  jwt_token_creds: _.partial(authTest, AUTH_USER, null),
  oauth2_auth_token: _.partial(oauth2Test, AUTH_USER, AUTH_SCOPE, false),
  per_rpc_creds: _.partial(oauth2Test, AUTH_USER, AUTH_SCOPE, true)
};

/**
 * Execute a single test case.
 * @param {string} address The address of the server to connect to, in the
 *     format 'hostname:port'
 * @param {string} host_overrirde The hostname of the server to use as an SSL
 *     override
 * @param {string} test_case The name of the test case to run
 * @param {bool} tls Indicates that a secure channel should be used
 * @param {function} done Callback to call when the test is completed. Included
 *     primarily for use with mocha
 */
function runTest(address, host_override, test_case, tls, test_ca, done) {
  // TODO(mlumish): enable TLS functionality
  var options = {};
  if (tls) {
    var ca_path;
    if (test_ca) {
      ca_path = path.join(__dirname, '../test/data/ca.pem');
    } else {
      ca_path = process.env.SSL_CERT_FILE;
    }
    var ca_data = fs.readFileSync(ca_path);
    var creds = grpc.Credentials.createSsl(ca_data);
    options.credentials = creds;
    if (host_override) {
      options['grpc.ssl_target_name_override'] = host_override;
    }
  }
  var client = new testProto.TestService(address, options);

  test_cases[test_case](client, done);
}

if (require.main === module) {
  var parseArgs = require('minimist');
  var argv = parseArgs(process.argv, {
    string: ['server_host', 'server_host_override', 'server_port', 'test_case',
             'use_tls', 'use_test_ca']
  });
  runTest(argv.server_host + ':' + argv.server_port, argv.server_host_override,
          argv.test_case, argv.use_tls === 'true', argv.use_test_ca === 'true',
          function () {
            console.log('OK:', argv.test_case);
          });
}

/**
 * See docs for runTest
 */
exports.runTest = runTest;
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict'

const ghauth     = require('ghauth')
    , ghpulls    = require('ghpulls')
    , hyperquest = require('hyperquest')
    , bl         = require('bl')
    , map        = require('map-async')
    , decodeMime = require('mimelib').decodeMimeWord
    , gitexec    = require('gitexec')
    , split2     = require('split2')
    , listStream = require('list-stream')
    , after      = require('after')
    , columnify  = require('columnify')
    , argv       = require('minimist')(process.argv.slice(2))

const defaultDays   = 7
    , defaultOrg    = 'nodejs'
    , defaultRepo   = 'node'
    , days          = Number(argv.days) || Number(argv.d) || defaultDays
    , afterDate     = new Date(Date.now() - 1000 * 60 * 60 * 24 * days)
    , org           = (argv._[0] && argv._[0].split('/')[0]) || defaultOrg
    , repo          = (argv._[0] && argv._[0].split('/')[1]) || defaultRepo
    , authOptions   = { configName: 'iojs-tools' }
    , gitEmailCmd   = `git log --format="%aE" --until='${days} days ago' | sort | uniq`
    , gitDaysAgoCmd = `git log --since="${days} days ago" --format=%H | tail -1`
    , gitMailmapCmd = `git show {{ref}}:.mailmap`
    , dir           = process.cwd()

const done = after(3, onDataComplete)

let gitEmails
  , pullRequests
  , mailmap

gitexec.execCollect(dir, 'git remote -v', (err, remotes) => {
  if (!err && !new RegExp(`github\\.com[/:]${org}/${repo}\.git`).test(remotes))
    console.warn(`WARNING: could not find ${org}/${repo} in the list of remotes for this git repository, perhaps you should supply an 'org/repo' argument?`)
})

gitexec.exec(dir, gitEmailCmd)
  .pipe(split2())
  .pipe(listStream((err, emails) => {
    if (err)
      return done(err)

    emails = emails.map((email) => email.toString())
    gitEmails = emails
    console.log(`Found ${gitEmails.length} email addresses in git log up to ${days} days ago for ${dir}...`)
    done()
  }))

gitexec.execCollect(dir, gitDaysAgoCmd, (err, ref) => {
  if (!ref) {
    console.log(`Could not find a ${dir}/.mailmap from ${days} ago, ignoring...`)
    return done()
  }

  ref = ref.replace(/[\r\n\s]+/g, '')

  gitexec.execCollect(dir, gitMailmapCmd.replace(/\{\{ref\}\}/g, ref), (err, mailmap) => {
    if (err) {
      console.log(`Could not find a ${dir}/.mailmap from ${days} ago, ignoring...`)
      return done()
    }

    console.log(`Loaded ${days} days old ${dir}/.mailmap with ${mailmap.split(/[\n\r]+/).length} entries...`)

    done()
  })
})

getPullRequestData((err, list) => {
  if (err)
    return done(err)

  pullRequests = list
  done()
})

function getPullRequestData (callback) {
  function processList (err, list) {
    if (err)
      throw err

    list = list.filter(Boolean).map((pr) => {
      return {
          name    : pr.from_name
        , email   : pr.from_email
        , contact : `${pr.from_name} <${pr.from_email}>`
        , url     : pr.html_url
        , title   : pr.title
        , number  : `#${pr.number}`
      }
    })

    callback(null, list)
  }

  ghauth(authOptions, (err, authData) => {
    if (err)
      throw err

    ghpulls.list(authData, org, repo, { state: 'all', afterDate }, (err, list) => {
      if (err)
        throw err

      console.log(`Checking ${list.length} pull requests for ${org}/${repo}...`)
      map(list, collectAuthor, processList)
    })
  })
}

function collectAuthor (pull, callback) {
  const url = `https://patch-diff.githubusercontent.com/raw/${org}/${repo}/pull/${pull.number}.patch`

  hyperquest.get(url).pipe(bl((err, data) => {
    if (err)
      return callback(err)

    data = data.toString().replace(/\n\s+/g, ' ')

    const from = data.toString().match(/^From: (.+) <([^>]+)>$/m)
    if (!from)
      return callback()
      //return callback(new Error(`No 'From:' in patch for #${pull.number}`))

    pull.from_name  = from[1].split(/\s/).map((w) => decodeMime(w)).join(' ')
    pull.from_email = from[2]

    callback(null, pull)
  }))
}

function onDataComplete (err) {
  if (err)
    throw err

  pullRequests = pullRequests.filter((pr) => {
    if (mailmap && mailmap.indexOf(`<${pr.email}>`) > -1)
      return false

    if (gitEmails.indexOf(pr.email) > -1)
      return false

    return true
  })

  console.log(`\nNew contributors for the last ${days} day${days == 1 ? '' : 's:'}\n`)
  console.log(columnify(pullRequests, {
    columns: [ 'number', 'contact', 'title', 'url' ]
  }))
}
<commit_msg>updated mailmap load msg<commit_after>#!/usr/bin/env node

'use strict'

const ghauth     = require('ghauth')
    , ghpulls    = require('ghpulls')
    , hyperquest = require('hyperquest')
    , bl         = require('bl')
    , map        = require('map-async')
    , decodeMime = require('mimelib').decodeMimeWord
    , gitexec    = require('gitexec')
    , split2     = require('split2')
    , listStream = require('list-stream')
    , after      = require('after')
    , columnify  = require('columnify')
    , argv       = require('minimist')(process.argv.slice(2))

const defaultDays   = 7
    , defaultOrg    = 'nodejs'
    , defaultRepo   = 'node'
    , days          = Number(argv.days) || Number(argv.d) || defaultDays
    , afterDate     = new Date(Date.now() - 1000 * 60 * 60 * 24 * days)
    , org           = (argv._[0] && argv._[0].split('/')[0]) || defaultOrg
    , repo          = (argv._[0] && argv._[0].split('/')[1]) || defaultRepo
    , authOptions   = { configName: 'iojs-tools' }
    , gitEmailCmd   = `git log --format="%aE" --until='${days} days ago' | sort | uniq`
    , gitDaysAgoCmd = `git log --since="${days} days ago" --format=%H | tail -1`
    , gitMailmapCmd = `git show {{ref}}:.mailmap`
    , dir           = process.cwd()

const done = after(3, onDataComplete)

let gitEmails
  , pullRequests
  , mailmap

gitexec.execCollect(dir, 'git remote -v', (err, remotes) => {
  if (!err && !new RegExp(`github\\.com[/:]${org}/${repo}\.git`).test(remotes))
    console.warn(`WARNING: could not find ${org}/${repo} in the list of remotes for this git repository, perhaps you should supply an 'org/repo' argument?`)
})

gitexec.exec(dir, gitEmailCmd)
  .pipe(split2())
  .pipe(listStream((err, emails) => {
    if (err)
      return done(err)

    emails = emails.map((email) => email.toString())
    gitEmails = emails
    console.log(`Found ${gitEmails.length} email addresses in git log up to ${days} days ago for ${dir}...`)
    done()
  }))

gitexec.execCollect(dir, gitDaysAgoCmd, (err, ref) => {
  if (!ref) {
    console.log(`Could not find a ${dir}/.mailmap from ${days} ago, ignoring...`)
    return done()
  }

  ref = ref.replace(/[\r\n\s]+/g, '')

  gitexec.execCollect(dir, gitMailmapCmd.replace(/\{\{ref\}\}/g, ref), (err, mailmap) => {
    if (err) {
      console.log(`Could not find a ${dir}/.mailmap from ${days} ago, ignoring...`)
      return done()
    }

    console.log(`Loaded ${dir}/.mailmap from ${days} ago with ${mailmap.split(/[\n\r]+/).length} entries...`)

    done()
  })
})

getPullRequestData((err, list) => {
  if (err)
    return done(err)

  pullRequests = list
  done()
})

function getPullRequestData (callback) {
  function processList (err, list) {
    if (err)
      throw err

    list = list.filter(Boolean).map((pr) => {
      return {
          name    : pr.from_name
        , email   : pr.from_email
        , contact : `${pr.from_name} <${pr.from_email}>`
        , url     : pr.html_url
        , title   : pr.title
        , number  : `#${pr.number}`
      }
    })

    callback(null, list)
  }

  ghauth(authOptions, (err, authData) => {
    if (err)
      throw err

    ghpulls.list(authData, org, repo, { state: 'all', afterDate }, (err, list) => {
      if (err)
        throw err

      console.log(`Checking ${list.length} pull requests for ${org}/${repo}...`)
      map(list, collectAuthor, processList)
    })
  })
}

function collectAuthor (pull, callback) {
  const url = `https://patch-diff.githubusercontent.com/raw/${org}/${repo}/pull/${pull.number}.patch`

  hyperquest.get(url).pipe(bl((err, data) => {
    if (err)
      return callback(err)

    data = data.toString().replace(/\n\s+/g, ' ')

    const from = data.toString().match(/^From: (.+) <([^>]+)>$/m)
    if (!from)
      return callback()
      //return callback(new Error(`No 'From:' in patch for #${pull.number}`))

    pull.from_name  = from[1].split(/\s/).map((w) => decodeMime(w)).join(' ')
    pull.from_email = from[2]

    callback(null, pull)
  }))
}

function onDataComplete (err) {
  if (err)
    throw err

  pullRequests = pullRequests.filter((pr) => {
    if (mailmap && mailmap.indexOf(`<${pr.email}>`) > -1)
      return false

    if (gitEmails.indexOf(pr.email) > -1)
      return false

    return true
  })

  console.log(`\nNew contributors for the last ${days} day${days == 1 ? '' : 's:'}\n`)
  console.log(columnify(pullRequests, {
    columns: [ 'number', 'contact', 'title', 'url' ]
  }))
}
<|endoftext|>


<commit_before>/***********************************************************************************/
/*
 File:    weathernode.js
 Purpose: Main node file for the weather station qwesta
 Author:  Christian Kuster, CH-8342 Wernetshausen, www.kusti.ch, 22.9.14
 Github:  https://github.com/ancasicolica/qwesta

 ----------------------------------------------------------------------------------

 This is free and unencumbered software released into the public domain.

 Anyone is free to copy, modify, publish, use, compile, sell, or
 distribute this software, either in source code form or as a compiled
 binary, for any purpose, commercial or non-commercial, and by any
 means.

 In jurisdictions that recognize copyright laws, the author or authors
 of this software dedicate any and all copyright interest in the
 software to the public domain. We make this dedication for the benefit
 of the public at large and to the detriment of our heirs and
 successors. We intend this dedication to be an overt act of
 relinquishment in perpetuity of all present and future rights to this
 software under copyright law.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.

 For more information, please refer to <http://unlicense.org/>

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

var settings = require('./settings');
if (settings.simulator) {
  console.log('QWESTA SIMULATOR ACTIVE');
}
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
var weather = require('./weatherrecord.js');

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

var app = express();
/**
 * Get the file /ajax/current.html
 * This file contains the current records and is generated
 */
app.get('/ajax/current.html', function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(weather.getNewestRecords());
});

/**
 * Get the file /ajax/temperature.html
 * This file contains the available temperature data and is generated
 */
app.get('/ajax/temperature.html', function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(weather.getTemperatureDataAsJson());
});

/**
 * Get the file /ajax/humidity.html
 * This file contains the available temperature data and is generated
 */
app.get('/ajax/humidity.html', function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(weather.getHumidityDataAsJson());
});

/**
 * Get every other file (available in the filesystem)
 */
app.get('*', function (request, response) {

  var uri = url.parse(request.url).pathname;
  var filename = path.join(settings.htmlRootPath, uri);

  fs.exists(filename, function (exists) {
    if (!exists) {
      // File does not exist. Generated files were handled before.
      response.writeHead(404, {'Content-Type': 'text/plain'});
      response.write("Server root: " + process.cwd() + "\n");
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) {
      // default for directories: index.html
      filename += '/index.html';
    }

    // Read the file and stream it (at least try to...)
    fs.readFile(filename, 'binary', function (err, file) {
      if (err) {
        response.writeHead(500, {'Content-Type': 'text/plain'});
        response.write(err + '\n');
        response.end();
        return;
      }

      response.writeHead(200, {'Content-Type': mime.lookup(filename)});
      response.write(file, 'binary');
      response.end();
    });
  });
});

http.createServer(app).listen(settings.localServerPort);

console.log('Weather server is running at http://localhost:' + settings.localServerPort + '/\nCTRL + C to shutdown');

/***********************************************************************************/
// Serial port handling
/***********************************************************************************/
var serialport = require('serialport');
var SerialPort = serialport.SerialPort;

if (settings.simulator) {
  weather.startSimulator();
}

/**
 * Serialport object for the USB-WDE1-2
 * @type {SerialPort} Baudrate is 9600 bps, line parser is essential!
 */
var sp = new SerialPort(settings.serialComPort, {
  baudrate: 9600,
  parser  : serialport.parsers.readline('\n')
}, false); // this is the openImmediately flag [default is true]

/**
 * Open the serial port
 */
sp.open(function () {
  console.log('Serialport opened');

  // handles the incoming data, creates a new weather record
  sp.on('data', function (data) {
    var r = weather.newRecord(data);
    if (r != null) {
      console.log('data received: ' + r.toString());
    }
  });
});
<commit_msg>Debug log for 404 reason<commit_after>/***********************************************************************************/
/*
 File:    weathernode.js
 Purpose: Main node file for the weather station qwesta
 Author:  Christian Kuster, CH-8342 Wernetshausen, www.kusti.ch, 22.9.14
 Github:  https://github.com/ancasicolica/qwesta

 ----------------------------------------------------------------------------------

 This is free and unencumbered software released into the public domain.

 Anyone is free to copy, modify, publish, use, compile, sell, or
 distribute this software, either in source code form or as a compiled
 binary, for any purpose, commercial or non-commercial, and by any
 means.

 In jurisdictions that recognize copyright laws, the author or authors
 of this software dedicate any and all copyright interest in the
 software to the public domain. We make this dedication for the benefit
 of the public at large and to the detriment of our heirs and
 successors. We intend this dedication to be an overt act of
 relinquishment in perpetuity of all present and future rights to this
 software under copyright law.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.

 For more information, please refer to <http://unlicense.org/>

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

var settings = require('./settings');
if (settings.simulator) {
  console.log('QWESTA SIMULATOR ACTIVE');
}
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
var weather = require('./weatherrecord.js');

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

var app = express();
/**
 * Get the file /ajax/current.html
 * This file contains the current records and is generated
 */
app.get('/ajax/current.html', function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(weather.getNewestRecords());
});

/**
 * Get the file /ajax/temperature.html
 * This file contains the available temperature data and is generated
 */
app.get('/ajax/temperature.html', function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(weather.getTemperatureDataAsJson());
});

/**
 * Get the file /ajax/humidity.html
 * This file contains the available temperature data and is generated
 */
app.get('/ajax/humidity.html', function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(weather.getHumidityDataAsJson());
});

/**
 * Get every other file (available in the filesystem)
 */
app.get('*', function (request, response) {

  var uri = url.parse(request.url).pathname;
  var filename = path.join(settings.htmlRootPath, uri);

  fs.exists(filename, function (exists) {
    if (!exists) {
      // File does not exist. Generated files were handled before.
      response.writeHead(404, {'Content-Type': 'text/plain'});
      response.write("Server root: " + settings.htmlRootPath + "\n");
      response.write("Requested file: " + filename + "\n");
      response.write("404 Not Found\n");
      response.end();
      return;
    }

    if (fs.statSync(filename).isDirectory()) {
      // default for directories: index.html
      filename += '/index.html';
    }

    // Read the file and stream it (at least try to...)
    fs.readFile(filename, 'binary', function (err, file) {
      if (err) {
        response.writeHead(500, {'Content-Type': 'text/plain'});
        response.write(err + '\n');
        response.end();
        return;
      }

      response.writeHead(200, {'Content-Type': mime.lookup(filename)});
      response.write(file, 'binary');
      response.end();
    });
  });
});

http.createServer(app).listen(settings.localServerPort);

console.log('Weather server is running at http://localhost:' + settings.localServerPort + '/\nCTRL + C to shutdown');

/***********************************************************************************/
// Serial port handling
/***********************************************************************************/
var serialport = require('serialport');
var SerialPort = serialport.SerialPort;

if (settings.simulator) {
  weather.startSimulator();
}

/**
 * Serialport object for the USB-WDE1-2
 * @type {SerialPort} Baudrate is 9600 bps, line parser is essential!
 */
var sp = new SerialPort(settings.serialComPort, {
  baudrate: 9600,
  parser  : serialport.parsers.readline('\n')
}, false); // this is the openImmediately flag [default is true]

/**
 * Open the serial port
 */
sp.open(function () {
  console.log('Serialport opened');

  // handles the incoming data, creates a new weather record
  sp.on('data', function (data) {
    var r = weather.newRecord(data);
    if (r != null) {
      console.log('data received: ' + r.toString());
    }
  });
});
<|endoftext|>


<commit_before>//by DAVI すべての最強!
window.externalScriptMassBarTemp=0
class MassBar {
    constructor() {
        this.querys()

        this.buildElements()
        this.setStyleToElements()
        this.setClassToElements()
    }

    querys() {
        this.players         = document.getElementsByClassName('top5-mass-color')
        this.topTotalPlayers = document.getElementById('top5-total-players')

        this.topTotalMass    = document.getElementById('top5-total-mass')
        this.massesBar       = document.getElementsByClassName('mass-bar')
    }

    bringPlayersMass() {
        this.topMassLeaderboard =  Array.prototype.map.call(this.players, (mass, index) => {
            const calculatedMass = mass.innerText.match(/[k]/)
            ?
                Number(mass.innerText.match(/[0-9\.]/g).join('')) * 1000
            :
                Number(mass.innerText.match(/[0-9]/g).join(''))

            if (index < Number(this.topTotalPlayers.innerText)) {
                return calculatedMass
            }
        })
        .filter(mass => mass != undefined)
    }

    buildElements() {
        this.massBarContainer = document.createElement('div')
        this.massBar          = document.createElement('div')
    }

    setStyleToElements() {
		if (defaultSettings && defaultSettings.top5MassColor){
			this.massBarContainer.setAttribute('style', 'background-color: ' + defaultSettings.top5MassColor + '; display: block; position: relative; margin-bottom: 3px;')
		}
        else{
			this.massBarContainer.setAttribute('style', 'background-color: #202020; display: block; position: relative; margin-bottom: 3px;')
		}
        this.massBar.setAttribute('style', 'background-color: #01d9cc; width: 0%; height: 100%; max-width: 190px; left: 0px; top: 0px; position: absolute;')
    }

    setClassToElements() {
        this.massBarContainer.className = 'hud'
        this.massBar.className          = 'mass-bar'
    }

    buildMassHud() {
        this.massBarContainer.appendChild(this.massBar)
        const rankOositions = document.getElementById('top5-pos').getElementsByTagName('li')

        if (document.getElementsByClassName('mass-bar')[0] == undefined) {
            Array.prototype.forEach.call(rankOositions, rank => {
				window.externalScriptMassBar[window.externalScriptMassBarTemp]=this.massBarContainer.outerHTML
                //rank.insertAdjacentHTML('afterend', this.massBarContainer.outerHTML)
				window.externalScriptMassBarTemp++
            })

        }
    }

    setPercentage() {
        const calculatedMass = this.topTotalMass.innerText.match(/[k]/) != null
            ?
                Number(this.topTotalMass.innerText.match(/[0-9\.]/g).join('')) * 1000
            :
                Number(this.topTotalMass.innerText.match(/[0-9]/g).join(''))

        Array.prototype.forEach.call(this.massesBar, (massBar, index) => {
            massBar.style.width =  this.topMassLeaderboard[index] / calculatedMass * 100 + '%'
        })
    }
}

let massBar = new MassBar()

let observer = new MutationObserver(_ => {
    massBar.bringPlayersMass()
    massBar.setPercentage()
})

let analysis = {
    childList: true
}

setTimeout(function() {
let elementObserved = document.getElementById('top5-total-mass')
observer.observe(elementObserved, analysis)

 setInterval(_ => {
    massBar.buildMassHud()
    massBar.bringPlayersMass()
    massBar.setPercentage()
})
}, 5000);
<commit_msg>Update legendmodAddonDAVI.js<commit_after>//by DAVI すべての最強!
window.externalScriptMassBarTemp=0
var defaultSettings;
class MassBar {
    constructor() {
        this.querys()

        this.buildElements()
        this.setStyleToElements()
        this.setClassToElements()
    }

    querys() {
        this.players         = document.getElementsByClassName('top5-mass-color')
        this.topTotalPlayers = document.getElementById('top5-total-players')

        this.topTotalMass    = document.getElementById('top5-total-mass')
        this.massesBar       = document.getElementsByClassName('mass-bar')
    }

    bringPlayersMass() {
        this.topMassLeaderboard =  Array.prototype.map.call(this.players, (mass, index) => {
            const calculatedMass = mass.innerText.match(/[k]/)
            ?
                Number(mass.innerText.match(/[0-9\.]/g).join('')) * 1000
            :
                Number(mass.innerText.match(/[0-9]/g).join(''))

            if (index < Number(this.topTotalPlayers.innerText)) {
                return calculatedMass
            }
        })
        .filter(mass => mass != undefined)
    }

    buildElements() {
        this.massBarContainer = document.createElement('div')
        this.massBar          = document.createElement('div')
    }

    setStyleToElements() {
		if (defaultSettings && defaultSettings.top5MassColor){
			this.massBarContainer.setAttribute('style', 'background-color: ' + defaultSettings.top5MassColor + '; display: block; position: relative; margin-bottom: 3px;')
		}
        else{
			this.massBarContainer.setAttribute('style', 'background-color: #202020; display: block; position: relative; margin-bottom: 3px;')
		}
        this.massBar.setAttribute('style', 'background-color: #01d9cc; width: 0%; height: 100%; max-width: 190px; left: 0px; top: 0px; position: absolute;')
    }

    setClassToElements() {
        this.massBarContainer.className = 'hud'
        this.massBar.className          = 'mass-bar'
    }

    buildMassHud() {
        this.massBarContainer.appendChild(this.massBar)
        const rankOositions = document.getElementById('top5-pos').getElementsByTagName('li')

        if (document.getElementsByClassName('mass-bar')[0] == undefined) {
            Array.prototype.forEach.call(rankOositions, rank => {
				window.externalScriptMassBar[window.externalScriptMassBarTemp]=this.massBarContainer.outerHTML
                //rank.insertAdjacentHTML('afterend', this.massBarContainer.outerHTML)
				window.externalScriptMassBarTemp++
            })

        }
    }

    setPercentage() {
        const calculatedMass = this.topTotalMass.innerText.match(/[k]/) != null
            ?
                Number(this.topTotalMass.innerText.match(/[0-9\.]/g).join('')) * 1000
            :
                Number(this.topTotalMass.innerText.match(/[0-9]/g).join(''))

        Array.prototype.forEach.call(this.massesBar, (massBar, index) => {
            massBar.style.width =  this.topMassLeaderboard[index] / calculatedMass * 100 + '%'
        })
    }
}

let massBar = new MassBar()

let observer = new MutationObserver(_ => {
    massBar.bringPlayersMass()
    massBar.setPercentage()
})

let analysis = {
    childList: true
}

setTimeout(function() {
let elementObserved = document.getElementById('top5-total-mass')
observer.observe(elementObserved, analysis)

 setInterval(_ => {
    massBar.buildMassHud()
    massBar.bringPlayersMass()
    massBar.setPercentage()
})
}, 5000);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 PepperNote developers
 *
 * See the file license.txt for copying permission.
 */

var ENABLE_FIREBUG = false;

/**
 * Notifies the Qt app that selection changed
 */
function notifySelectionChange() {
    // Put function body in setTimeout so that the selection changes before
    // getting the computed style
    setTimeout(function() {
        var computed = getSelectionStyle();
        if (computed) {
            var fontFamily = computed['font-family'];
            var fontSize = getComputedFontPointSize(computed);
            Api.selectionChanged(fontFamily, fontSize);
        }
    }, 0);
}

/**
 * Notifies the Qt app that the #page_title changed
 */
function notifyTitleChange() {
    var pageTitleElement = $('page_title');
    var pageTitle = pageTitleElement ? pageTitleElement.innerText : '';
    pageTitle = pageTitle.strip();
    if (!pageTitle)
        return;

    Api.notifyTitleChanged(pageTitle);
}

/**
 * If any part of the body is clicked outside of the editable area, the cursor
 * is placed at the end of the #page_content.
 *
 * NOTE:  For this to work, body height must be 100%.
 */
function acceptAllClicks() {
    var noteContentClicked = false;

    document.body.observe('click', function(event) {
        if (!noteContentClicked)
            putCursorAtEnd($('page_content'));
        noteContentClicked = false;
    });

    $('page_content').observe('click', function(event) {
        noteContentClicked = true;
    });
}

document.observe('dom:loaded', function() {
    if (ENABLE_FIREBUG)
        addFirebug();

    // Clicks outside the editable area are caught
    acceptAllClicks();

    // Notify the Qt app when the selection changes.  This allows the app to
    // set its controls based on the current selection (e.g. formatting
    // controls).
    $('page_content').observe('selectstart', notifySelectionChange);

    // TODO:  restore cursor position instead of putting it at the end
    putCursorAtEnd($('page_content'));
});

/**
 * Invoked by the native app when the #page_content is loaded
 */
function pageLoaded() {
    var pageTitleElement = $('page_title');
    if (pageTitleElement) {
        // Check to see if the #page_title should be updated from the default
        // page template by checking for this global variable
        if (typeof initialPageTitle !== 'undefined')
            pageTitleElement.update(initialPageTitle);

        pageTitleElement.observe('DOMCharacterDataModified', notifyTitleChange);
    }
}
<commit_msg>Clear initialPageTitle after using it in JS pageLoaded()<commit_after>/*
 * Copyright (c) 2012 PepperNote developers
 *
 * See the file license.txt for copying permission.
 */

var ENABLE_FIREBUG = false;

/**
 * Notifies the Qt app that selection changed
 */
function notifySelectionChange() {
    // Put function body in setTimeout so that the selection changes before
    // getting the computed style
    setTimeout(function() {
        var computed = getSelectionStyle();
        if (computed) {
            var fontFamily = computed['font-family'];
            var fontSize = getComputedFontPointSize(computed);
            Api.selectionChanged(fontFamily, fontSize);
        }
    }, 0);
}

/**
 * Notifies the Qt app that the #page_title changed
 */
function notifyTitleChange() {
    var pageTitleElement = $('page_title');
    var pageTitle = pageTitleElement ? pageTitleElement.innerText : '';
    pageTitle = pageTitle.strip();
    if (!pageTitle)
        return;

    Api.notifyTitleChanged(pageTitle);
}

/**
 * If any part of the body is clicked outside of the editable area, the cursor
 * is placed at the end of the #page_content.
 *
 * NOTE:  For this to work, body height must be 100%.
 */
function acceptAllClicks() {
    var noteContentClicked = false;

    document.body.observe('click', function(event) {
        if (!noteContentClicked)
            putCursorAtEnd($('page_content'));
        noteContentClicked = false;
    });

    $('page_content').observe('click', function(event) {
        noteContentClicked = true;
    });
}

document.observe('dom:loaded', function() {
    if (ENABLE_FIREBUG)
        addFirebug();

    // Clicks outside the editable area are caught
    acceptAllClicks();

    // Notify the Qt app when the selection changes.  This allows the app to
    // set its controls based on the current selection (e.g. formatting
    // controls).
    $('page_content').observe('selectstart', notifySelectionChange);

    // TODO:  restore cursor position instead of putting it at the end
    putCursorAtEnd($('page_content'));
});

/**
 * Invoked by the native app when the #page_content is loaded
 */
function pageLoaded() {
    var pageTitleElement = $('page_title');
    if (pageTitleElement) {
        // Check to see if the #page_title should be updated from the default
        // page template by checking for this global variable
        if (typeof initialPageTitle !== 'undefined' && initialPageTitle) {
            pageTitleElement.update(initialPageTitle);
            initialPageTitle = null;
        }

        pageTitleElement.observe('DOMCharacterDataModified', notifyTitleChange);
    }
}
<|endoftext|>