<commit_before>var Discord = require('discord.js');
var fs = require('fs');
var path = require('path');
var http = require('http');
var moment = require('moment');
moment().format();
var k2 = new Discord.Client();

var token;
if (fs.existsSync('token')) {
	token = fs.readFileSync('token', 'utf8').replace(/^\s+|\s+$/g,'');
}
else {
	token = process.env.TOKEN;
	// to keep Heroku happy
	http.createServer(function(req,res) {
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.write('K-2SO is operational.\n');
	}).listen(process.env.PORT);
}
k2.login(token);

function sleep (ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
} // sleep

k2.on("ready", function (rawEvent) {
	console.log("Connected to server");
	k2.user.setPresence({ game : { name : '!k2help' }});
}); // on.ready

var responseDict = {
	"hello": "The captain says you're a friend. I will not kill you.",
	"goodbye" : "Good riddance.",
	"hug" : "I'm not giving you a hug.",
	"k2help" : "You know, I'm not that complicated. You can just figure it out.",
	"fliptable" : "(╯°□°)╯︵ ┻━┻"
}

var contestInProgress = false;
var contestEndTime;
var contestDetails;
var contestNumParticipants;
var contestParticipants = [];
var functionDict = {
    "contest": function() {
        if (contestInProgress) {
            this.reply("There is already a contest in progress.");
            return;
        }
        var arguments = this.content.substring(1).split("!");
        arguments.shift(); // just the arguments
        if (arguments.length !== 2) {
            this.channel.sendMessage("The syntax of this command is: \n" +
				"!contest !<what you are giving away> !<how long the contest will last" +
				" [minutes]>", { code : true });
            return;
        }
        contestInProgress = true;
        contestNumParticipants = contestParticipants.push("No one");
        this.channel.sendMessage("@everyone, a contest has begun! " + this.author +
            " is giving away " + arguments[0] + " in " + arguments[1] + " minute(s)! " +
            "Use !entercontest to enter the contest!");
		contestEndTime = moment.add(arguments[1], 'minutes').format('LLL');
		contestDetails = [ this.author, arguments[0], contestEndTime ];
        setTimeout(function(message, prize) {
            message.channel.sendMessage("@everyone, " + message.author + "'s contest has ended! " +
				"Out of " + (contestParticipants.length-1).toString() + " entries, " +
				contestParticipants[Math.ceil(Math.random()*(contestParticipants.length-1))] +
                " has won " + prize + "!");
		contestParticipants = [];
		contestInProgress = false;
        }, 1000*60*arguments[1], this, arguments[0]);
    },
    "entercontest": function() {
        if (!contestInProgress) {
            this.reply("What contest?");
            return;
        }
        if (contestParticipants.indexOf(this.author) !== -1) {
            this.reply("Only one entry per person. That is, unless you know a guy.");
            return;
        }
        contestNumParticipants = contestParticipants.push(this.author);
        this.channel.sendMessage("Your entry has been received. Good luck!");
    },
	"conteststatus": function() {
		if (!contestInProgress) {
			this.reply("What contest?");
			return;
		}
		this.channel.sendMessage("The current contest was started by " + contestDetails[0] +
			", the prize is " + contestDetails[1] + ", and the contest ends at " +
			contestDetails[2] + ".");
	},
    "endcontest": function() {
        if (!contestInProgress) {
            this.reply("What contest?");
            return;
        }
		if (this.author !== contestDetails[0]) {
			this.channel.sendMessage("This isn't your contest.");
			return;
		}
        contestInProgress = false;
        this.channel.sendMessage("@everyone, " + this.author + " has ended the contest "  +
            "prematurely, similar to how their most recent sexual encounter ended.");
    },
    "currenttime": function() {
        this.reply("the current time is " + moment.format('LLL'));
    }
}

var audioTimeout = new Date();
function findInVoiceChannel(guild, userName) {
	return guild.channels.find(function(channel) {
		return (channel.type === "voice"
			&& channel.members.find(function(member) {
				return member.user.username === userName;
		})); // find member;
	});
} // findInVoiceChannel

function playAudioInChannel(tchannel, vchannel, path) {
	if (new Date().getTime() < audioTimeout) {
		tchannel.sendMessage("Have some patience.");
		return;
	}
	audioTimeout = new Date();
	audioTimeout = audioTimeout.setMinutes(audioTimeout.getMinutes() + 5);
	vchannel.join().then(connection => {
		console.log("Joined " + vchannel.name);
        setTimeout(function() {
            const dispatch = connection.playFile(path,
                { volume : 0.5 }, function(error, intent) {
                intent.on("error", function(err) {
                    console.log("playFile: " + error);
                })
            });
            dispatch.on('speaking',(val) =>  {
			if (!val) { connection.disconnect(); }
			})
			}, 750); })
        .catch(console.log);
	vchannel.leave();
	voiceReactInProgress = false;
}

k2.on("message", function (message) {
	var author = message.author;
	var channel = message.channel;
    if (message.content.substring(0, 1) == "!") {
        var arguments = message.content.substring(1).split(" ");
        var command = arguments[0];
        arguments.shift(); // just the arguments
        if (responseDict[command]) {
        	channel.sendMessage(responseDict[command]);
        } // if
        else if (functionDict[command]) {
            functionDict[command].call(message);
        }
    } // if
	// non-command responses
	else {
	 	if (message.toString().indexOf("JOHN CENA") !== -1) {
			message.react("\uD83D\uDCA5"); 	// boom
			message.react("\uD83C\uDFBA"); 	// trumpet
		} // if
		if (message.toString().toLowerCase().indexOf("who is champ?") !== -1) {
			console.log("Hint: It's John Cena");
			var vchannel = findInVoiceChannel(message.guild,
				author.username);
			if (vchannel == undefined) {
				message.reply("THAT QUESTION WILL BE ANSWERED THIS SUNDAY!");
			} // if
			else {
				voiceReactInProgress = true;
				playAudioInChannel(channel, vchannel, "audio/whoischamp.mp3");
				voiceReactInProgress = false;

			} // else
					} // if
	} // else
}); // on.message
<commit_msg>Oops()<commit_after>var Discord = require('discord.js');
var fs = require('fs');
var path = require('path');
var http = require('http');
var moment = require('moment');
moment().format();
var k2 = new Discord.Client();

var token;
if (fs.existsSync('token')) {
	token = fs.readFileSync('token', 'utf8').replace(/^\s+|\s+$/g,'');
}
else {
	token = process.env.TOKEN;
	// to keep Heroku happy
	http.createServer(function(req,res) {
		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.write('K-2SO is operational.\n');
	}).listen(process.env.PORT);
}
k2.login(token);

function sleep (ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
} // sleep

k2.on("ready", function (rawEvent) {
	console.log("Connected to server");
	k2.user.setPresence({ game : { name : '!k2help' }});
}); // on.ready

var responseDict = {
	"hello": "The captain says you're a friend. I will not kill you.",
	"goodbye" : "Good riddance.",
	"hug" : "I'm not giving you a hug.",
	"k2help" : "You know, I'm not that complicated. You can just figure it out.",
	"fliptable" : "(╯°□°)╯︵ ┻━┻"
}

var contestInProgress = false;
var contestEndTime;
var contestDetails;
var contestNumParticipants;
var contestParticipants = [];
var functionDict = {
    "contest": function() {
        if (contestInProgress) {
            this.reply("There is already a contest in progress.");
            return;
        }
        var arguments = this.content.substring(1).split("!");
        arguments.shift(); // just the arguments
        if (arguments.length !== 2) {
            this.channel.sendMessage("The syntax of this command is: \n" +
				"!contest !<what you are giving away> !<how long the contest will last" +
				" [minutes]>", { code : true });
            return;
        }
        contestInProgress = true;
        contestNumParticipants = contestParticipants.push("No one");
        this.channel.sendMessage("@everyone, a contest has begun! " + this.author +
            " is giving away " + arguments[0] + " in " + arguments[1] + " minute(s)! " +
            "Use !entercontest to enter the contest!");
		contestEndTime = moment().add(arguments[1], 'minutes').format('LLL');
		contestDetails = [ this.author, arguments[0], contestEndTime ];
        setTimeout(function(message, prize) {
            message.channel.sendMessage("@everyone, " + message.author + "'s contest has ended! " +
				"Out of " + (contestParticipants.length-1).toString() + " entries, " +
				contestParticipants[Math.ceil(Math.random()*(contestParticipants.length-1))] +
                " has won " + prize + "!");
		contestParticipants = [];
		contestInProgress = false;
        }, 1000*60*arguments[1], this, arguments[0]);
    },
    "entercontest": function() {
        if (!contestInProgress) {
            this.reply("What contest?");
            return;
        }
        if (contestParticipants.indexOf(this.author) !== -1) {
            this.reply("Only one entry per person. That is, unless you know a guy.");
            return;
        }
        contestNumParticipants = contestParticipants.push(this.author);
        this.channel.sendMessage("Your entry has been received. Good luck!");
    },
	"conteststatus": function() {
		if (!contestInProgress) {
			this.reply("What contest?");
			return;
		}
		this.channel.sendMessage("The current contest was started by " + contestDetails[0] +
			", the prize is " + contestDetails[1] + ", and the contest ends at " +
			contestDetails[2] + ".");
	},
    "endcontest": function() {
        if (!contestInProgress) {
            this.reply("What contest?");
            return;
        }
		if (this.author !== contestDetails[0]) {
			this.channel.sendMessage("This isn't your contest.");
			return;
		}
        contestInProgress = false;
        this.channel.sendMessage("@everyone, " + this.author + " has ended the contest "  +
            "prematurely, similar to how their most recent sexual encounter ended.");
    },
    "currenttime": function() {
        this.reply("the current time is " + moment().format('LLL'));
    }
}

var audioTimeout = new Date();
function findInVoiceChannel(guild, userName) {
	return guild.channels.find(function(channel) {
		return (channel.type === "voice"
			&& channel.members.find(function(member) {
				return member.user.username === userName;
		})); // find member;
	});
} // findInVoiceChannel

function playAudioInChannel(tchannel, vchannel, path) {
	if (new Date().getTime() < audioTimeout) {
		tchannel.sendMessage("Have some patience.");
		return;
	}
	audioTimeout = new Date();
	audioTimeout = audioTimeout.setMinutes(audioTimeout.getMinutes() + 5);
	vchannel.join().then(connection => {
		console.log("Joined " + vchannel.name);
        setTimeout(function() {
            const dispatch = connection.playFile(path,
                { volume : 0.5 }, function(error, intent) {
                intent.on("error", function(err) {
                    console.log("playFile: " + error);
                })
            });
            dispatch.on('speaking',(val) =>  {
			if (!val) { connection.disconnect(); }
			})
			}, 750); })
        .catch(console.log);
	vchannel.leave();
	voiceReactInProgress = false;
}

k2.on("message", function (message) {
	var author = message.author;
	var channel = message.channel;
    if (message.content.substring(0, 1) == "!") {
        var arguments = message.content.substring(1).split(" ");
        var command = arguments[0];
        arguments.shift(); // just the arguments
        if (responseDict[command]) {
        	channel.sendMessage(responseDict[command]);
        } // if
        else if (functionDict[command]) {
            functionDict[command].call(message);
        }
    } // if
	// non-command responses
	else {
	 	if (message.toString().indexOf("JOHN CENA") !== -1) {
			message.react("\uD83D\uDCA5"); 	// boom
			message.react("\uD83C\uDFBA"); 	// trumpet
		} // if
		if (message.toString().toLowerCase().indexOf("who is champ?") !== -1) {
			console.log("Hint: It's John Cena");
			var vchannel = findInVoiceChannel(message.guild,
				author.username);
			if (vchannel == undefined) {
				message.reply("THAT QUESTION WILL BE ANSWERED THIS SUNDAY!");
			} // if
			else {
				voiceReactInProgress = true;
				playAudioInChannel(channel, vchannel, "audio/whoischamp.mp3");
				voiceReactInProgress = false;

			} // else
					} // if
	} // else
}); // on.message
<|endoftext|>


<commit_before>'use strict';

angular.module('app')
  .controller('ServerDataCtrl', function ($scope, webSocket, Gateway, settings, RandomValueDataSource, WebSocketDataSource, TimeSeriesDataSource) {
    $scope.value1 = 'not defined';
    $scope.value2 = 'not defined';

    var widgetDefinitions = [
      {
        name: 'Value',
        directive: 'wt-scope-watch',
        dataAttrName: 'value',
        attrs: {
          'value-class': 'alert-info'
        },
        dataTypes: ['percentage', 'simple'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.piValue
        }
      },
      {
        name: 'Progressbar',
        directive: 'progressbar',
        attrs: {
          class: 'progress-striped',
          type: 'success'
        },
        dataAttrName: 'value',
        dataTypes: ['percentage', 'simple'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.progress
        }
      },
      {
        name: 'Line Chart',
        directive: 'wt-line-chart',
        dataAttrName: 'chart',
        dataTypes: ['timeseries'],
        dataSourceType: TimeSeriesDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.chartValue
        },
        style: {
          width: '50%'
        }
      },
      {
        name: 'TopN',
        directive: 'wt-top-n',
        attrs: {
          data: 'serverTopTen'
        },
        dataAttrName: 'data',
        dataTypes: ['topN'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.topn
        }
      },
      {
        name: 'Gauge',
        directive: 'wt-gauge',
        dataAttrName: 'value',
        dataTypes: ['percentage', 'simple'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.percentage
        },
        style: {
          width: '250px'
        }
      },
      {
        name: 'Topics',
        templateUrl: 'template/topics.html'
      },
      {
        name: 'JSON',
        directive: 'wt-json',
        dataAttrName: 'value',
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.topn
        }
      }
    ];

    function find(name) {
      return _.findWhere(widgetDefinitions, {name: name});
    }

    function copy(name, extend) {
      var dest = angular.copy(find(name));

      if (extend) {
        angular.extend(dest, extend);
      }

      return dest;
    }

    //var defaultWidgets = _.clone(widgetDefinitions);
    var defaultWidgets = [
      copy('Value', {
        title: 'Value 1'
      }),
      copy('Value', {
        title: 'Value 2',
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.percentage
        }
      }),
      copy('Progressbar', {
        title: 'Progressbar'
      }),
      copy('Line Chart', {
        title: 'Line Chart 1'
      }),
      copy('Line Chart', {
        title: 'Line Chart 2',
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.chartValue2
        }
      }),
      copy('TopN', {
        title: 'Top N'
      }),
      copy('Gauge', {
        title: 'Gauge'
      }),
      copy('JSON', {
        title: 'JSON'
      }),
      copy('Topics', {
        title: 'WebSocket Topics'
      })
    ];

    $scope.dashboardOptions = {
      widgetButtons: true,
      widgetDefinitions: widgetDefinitions,
      defaultWidgets: defaultWidgets,
      optionsTemplateUrl: 'template/widgetOptions.html'
    };

    // initialize widgets with default topics
    var topicsPromise = Gateway.getTopics();

    $scope.$on('widgetAdded', function (event, widget) {
      event.stopPropagation();

      if (widget.dataSource && widget.dataSourceOptions && widget.dataSourceOptions.defaultTopic) {
        topicsPromise.then(function (topics) {
          var defaultTopic = widget.dataSourceOptions.defaultTopic;

          var topic = _.find(topics, function (topic) {
            return topic.name.indexOf(defaultTopic) >= 0;
          });

          if (topic) {
            widget.dataSource.update(topic.topic);
          }
        });
      }
    });
  });<commit_msg>useLocalStorage: false<commit_after>'use strict';

angular.module('app')
  .controller('ServerDataCtrl', function ($scope, webSocket, Gateway, settings, RandomValueDataSource, WebSocketDataSource, TimeSeriesDataSource) {
    $scope.value1 = 'not defined';
    $scope.value2 = 'not defined';

    var widgetDefinitions = [
      {
        name: 'Value',
        directive: 'wt-scope-watch',
        dataAttrName: 'value',
        attrs: {
          'value-class': 'alert-info'
        },
        dataTypes: ['percentage', 'simple'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.piValue
        }
      },
      {
        name: 'Progressbar',
        directive: 'progressbar',
        attrs: {
          class: 'progress-striped',
          type: 'success'
        },
        dataAttrName: 'value',
        dataTypes: ['percentage', 'simple'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.progress
        }
      },
      {
        name: 'Line Chart',
        directive: 'wt-line-chart',
        dataAttrName: 'chart',
        dataTypes: ['timeseries'],
        dataSourceType: TimeSeriesDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.chartValue
        },
        style: {
          width: '50%'
        }
      },
      {
        name: 'TopN',
        directive: 'wt-top-n',
        attrs: {
          data: 'serverTopTen'
        },
        dataAttrName: 'data',
        dataTypes: ['topN'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.topn
        }
      },
      {
        name: 'Gauge',
        directive: 'wt-gauge',
        dataAttrName: 'value',
        dataTypes: ['percentage', 'simple'],
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.percentage
        },
        style: {
          width: '250px'
        }
      },
      {
        name: 'Topics',
        templateUrl: 'template/topics.html'
      },
      {
        name: 'JSON',
        directive: 'wt-json',
        dataAttrName: 'value',
        dataSourceType: WebSocketDataSource,
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.topn
        }
      }
    ];

    function find(name) {
      return _.findWhere(widgetDefinitions, {name: name});
    }

    function copy(name, extend) {
      var dest = angular.copy(find(name));

      if (extend) {
        angular.extend(dest, extend);
      }

      return dest;
    }

    //var defaultWidgets = _.clone(widgetDefinitions);
    var defaultWidgets = [
      copy('Value', {
        title: 'Value 1'
      }),
      copy('Value', {
        title: 'Value 2',
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.percentage
        }
      }),
      copy('Progressbar', {
        title: 'Progressbar'
      }),
      copy('Line Chart', {
        title: 'Line Chart 1'
      }),
      copy('Line Chart', {
        title: 'Line Chart 2',
        dataSourceOptions: {
          defaultTopic: settings.topic.visualdata.chartValue2
        }
      }),
      copy('TopN', {
        title: 'Top N'
      }),
      copy('Gauge', {
        title: 'Gauge'
      }),
      copy('JSON', {
        title: 'JSON'
      }),
      copy('Topics', {
        title: 'WebSocket Topics'
      })
    ];

    $scope.dashboardOptions = {
      useLocalStorage: false, //TODO enable by default
      widgetButtons: true,
      widgetDefinitions: widgetDefinitions,
      defaultWidgets: defaultWidgets,
      optionsTemplateUrl: 'template/widgetOptions.html'
    };

    // initialize widgets with default topics
    var topicsPromise = Gateway.getTopics();

    $scope.$on('widgetAdded', function (event, widget) {
      event.stopPropagation();

      if (widget.dataSource && widget.dataSourceOptions && widget.dataSourceOptions.defaultTopic) {
        topicsPromise.then(function (topics) {
          var defaultTopic = widget.dataSourceOptions.defaultTopic;

          var topic = _.find(topics, function (topic) {
            return topic.name.indexOf(defaultTopic) >= 0;
          });

          if (topic) {
            widget.dataSource.update(topic.topic);
          }
        });
      }
    });
  });<|endoftext|>


<commit_before>/**
 * @author Mugen87 / http://github.com/Mugen87
 */

import { BufferGeometry } from '../core/BufferGeometry.js';
import { BufferAttribute } from '../core/BufferAttribute.js';
import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
import { Line } from '../objects/Line.js';
import { _Math } from '../math/Math.js';

function PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {

	this.audio = audio;
 	this.range = range || 1;
 	this.divisionsInnerAngle = divisionsOuterAngle || 16;
	this.divisionsOuterAngle = divisionsOuterAngle || 2;

	var geometry = new BufferGeometry();
	var divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;
	var positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );
	geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );

	var materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );
	var materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );

	Line.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );

	this.update();

}

PositionalAudioHelper.prototype = Object.create( Line.prototype );
PositionalAudioHelper.prototype.constructor = PositionalAudioHelper;

PositionalAudioHelper.prototype.update = function () {

	var audio = this.audio;
	var range = this.range;
	var divisionsInnerAngle = this.divisionsInnerAngle;
	var divisionsOuterAngle = this.divisionsOuterAngle;

	var coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );
	var coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );

	var halfConeInnerAngle = coneInnerAngle / 2;
	var halfConeOuterAngle = coneOuterAngle / 2;

	var start = 0;
	var count = 0;
	var i, stride;

	var geometry = this.geometry;
	var positionAttribute = geometry.attributes.position;

	geometry.clearGroups();

	//

	function generateSegment( from, to, divisions, materialIndex ) {

		var step = ( to - from ) / divisions;

		positionAttribute.setXYZ( start, 0, 0, 0 );
		count ++;

		for ( i = from; i < to; i += step ) {

			stride = start + count;

			positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );
			positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );
			positionAttribute.setXYZ( stride + 2, 0, 0, 0 );

			count += 3;

		}

		geometry.addGroup( start, count, materialIndex );

		start += count;
		count = 0;

	}

	//

	generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );
	generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );
	generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );

	//

	positionAttribute.needsUpdate = true;

	if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;

};

PositionalAudioHelper.prototype.dispose = function () {

	this.geometry.dispose();
	this.material[ 0 ].dispose();
	this.material[ 1 ].dispose();

};

export { PositionalAudioHelper };
<commit_msg>PositionalAudioHelper: Clean up.<commit_after>/**
 * @author Mugen87 / http://github.com/Mugen87
 */

import { BufferGeometry } from '../core/BufferGeometry.js';
import { BufferAttribute } from '../core/BufferAttribute.js';
import { LineBasicMaterial } from '../materials/LineBasicMaterial.js';
import { Line } from '../objects/Line.js';
import { _Math } from '../math/Math.js';

function PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {

	this.audio = audio;
	this.range = range || 1;
	this.divisionsInnerAngle = divisionsOuterAngle || 16;
	this.divisionsOuterAngle = divisionsOuterAngle || 2;

	var geometry = new BufferGeometry();
	var divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;
	var positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );
	geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) );

	var materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );
	var materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );

	Line.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );

	this.update();

}

PositionalAudioHelper.prototype = Object.create( Line.prototype );
PositionalAudioHelper.prototype.constructor = PositionalAudioHelper;

PositionalAudioHelper.prototype.update = function () {

	var audio = this.audio;
	var range = this.range;
	var divisionsInnerAngle = this.divisionsInnerAngle;
	var divisionsOuterAngle = this.divisionsOuterAngle;

	var coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );
	var coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );

	var halfConeInnerAngle = coneInnerAngle / 2;
	var halfConeOuterAngle = coneOuterAngle / 2;

	var start = 0;
	var count = 0;
	var i, stride;

	var geometry = this.geometry;
	var positionAttribute = geometry.attributes.position;

	geometry.clearGroups();

	//

	function generateSegment( from, to, divisions, materialIndex ) {

		var step = ( to - from ) / divisions;

		positionAttribute.setXYZ( start, 0, 0, 0 );
		count ++;

		for ( i = from; i < to; i += step ) {

			stride = start + count;

			positionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );
			positionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );
			positionAttribute.setXYZ( stride + 2, 0, 0, 0 );

			count += 3;

		}

		geometry.addGroup( start, count, materialIndex );

		start += count;
		count = 0;

	}

	//

	generateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );
	generateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );
	generateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );

	//

	positionAttribute.needsUpdate = true;

	if ( coneInnerAngle === coneOuterAngle ) this.material[ 0 ].visible = false;

};

PositionalAudioHelper.prototype.dispose = function () {

	this.geometry.dispose();
	this.material[ 0 ].dispose();
	this.material[ 1 ].dispose();

};

export { PositionalAudioHelper };
<|endoftext|>


<commit_before>// require('./server.js');
var scripts = require('./scripts/scripts.js');
var dischord = require('discord.js');

// Set-up the MongoDB Client
// var MongoClient = require('mongodb').MongoClient;
// var assert = require('assert');
// var url = process.env.MONGODB_URI;

var bot = new dischord.Client({revive: true});

function searchGrimoire(input, message) {

    var stripeCmd = input.substr('8');

    bot.reply(message, "http://www.ishtar-collective.net/search/" + encodeURIComponent(stripeCmd));

}

function searchCard(input, message) {

        var stripeCmd = input.substr('6');
        var query = scripts.normalizeCardInput(stripeCmd);

        bot.reply(message, "http://www.ishtar-collective.net/cards/" + query);

}

function searchItems(input, message) {

        var stripeCmd = input.substr('6');
        var query = scripts.normalizeItemInput(stripeCmd);

        bot.reply(message, "http://www.ishtar-collective.net/items/" + query);

}

function help(input, message) {

    bot.sendMessage(message.author,
        "**LoreBot Help Menu**" +'\n'+'\n'+
        "**__Search Ishtar by Topic__**" +'\n'+
        "**!search** *your search topic*" +'\n'+
        "ex: `!search osiris`" +'\n'+
        "This will return a link such as - ishtar-collective.net/search/osiris" +'\n'+'\n'+
        "**__Search Ishtar for Grimoire Card__**" +'\n'+
        "**!card** *exact name of card you want to show in chat*"+'\n'+
        "ex: `!card osiris`" +'\n'+
        "This will return a link to the card, with first 50 or so characters and image of card. If not, then no card name matched your query. The link provided will still take you to Ishtar and give suggestions based on your query." +'\n'+'\n'+
        "**__Search Ishtar for Item__**" +'\n'+
        "**!item** *item you want to show in chat*" +'\n'+
        "ex: `!item ace of spades`" +'\n'+
        "This will, like the card command, return a link to the item or weapon along with the flavor text and an image of the item. If not, then your search did not match. Follow the link to Ishtar and check if it's suggestions match what you were looking for." +'\n'+'\n'+
        "**__NPC Quotes__**" +'\n'+
        "**!quotes** *the person your wanting the quotes from*" +'\n'+
        "ex: `!quotes mara`" +'\n'+
        "This will return a single random quote from Mara Sov. You can type in Mara, mara, mara sov or queen of the reef, etc to get these quotes." +'\n'+'\n'+
        "**__Display Help Menu__**" +'\n'+
        "`!lorehelp` - Displays this help menu" +'\n'+'\n');

}

/*function paean() {

    bot.on("message", function(message) {
        var input = message.content;
        var help = /(!help)/;
        var paean = /(paean)/i;
        var poster = message.author.id;
        var checkPoster = '159985870458322944';
        var checkForPaean = input.search(paean) != -1;
        var checkForHelp = input.search(help) != -1;
        var memes = [
            "http://sos.campmobile.net/e/2h28ej_g/he7Ud015a309a37y82it_awsowi.jpg",
            "http://sos.campmobile.net/e/2h28ef_6/bbjUd015pzbbt8dfcbse_hsmjp8.jpg",
            "http://sos.campmobile.net/d/2h204b_e/469Ud0151fl3ky5g3fy6u_o6iq9q.jpg",
            "http://sos.campmobile.net/d/2h28cd_d/2d5Ud015psn7vdj6a3wt_l0ky7l.jpg",
            "http://sos.campmobile.net/d/2h068g_i/3e8Ud0158cjt8r6d5mxb_l0ky7l.jpg",
            "https://cdn.discordapp.com/attachments/143886914326495233/186270379533139979/IMG_0800.GIF"
            ]
        var pick = memes[Math.round(Math.random()*(memes.length-1))];
        var name = pick.substr(40, 5);

        breakMyth: if ( checkPoster === poster ) {
            break breakMyth;
        } else if ( checkForPaean ) {
            bot.reply(message, "That does not return any results. But, I have noticed a pattern. Because I am a genius HE HE HE");
            bot.sendFile( message.channel, pick, name + filetype(pick));
        }
    });
}*/

function quotes (input, message) {

    var query = scripts.normalizeItemInput(input.substr('8')).replace(/\s+/g, "-");

    switch (query) {
        case "speaker":
        case "the-speaker":
            var qSpeaker = require('./assets/speaker.js');
            bot.sendMessage(message.channel, "**The Speaker: **" + scripts.randomQuote(qSpeaker));
            break;
        case "cayde":
        case "cayde-6":
            var qCayde = require('./assets/cayde.js');
            bot.sendMessage(message.channel, "**Cayde-6: **" + scripts.randomQuote(qCayde));
            break;
        case "ikora":
        case "ikora-rey":
            var qIkora = require('./assets/ikora.js');
            bot.sendMessage(message.channel, "**Ikora Rey: **" + scripts.randomQuote(qIkora));
            break;
        case "zavala":
        case "commander-zavala":
            var qZavala = require('./assets/zavala.js');
            bot.sendMessage(message.channel, "**Commander Zavala: **" + scripts.randomQuote(qZavala));
            break;
        case "xur":
        case "agent-of-the-nine":
        case "agent-of-the-9":
            var qXur = require('./assets/xur.js');
            bot.sendMessage(message.channel, "**Xur: **" + scripts.randomQuote(qXur));
            break;
        case "eris":
        case "eris-morn":
            var qEris = require('./assets/eris.js');
            bot.sendMessage(message.channel, "**Eris Morn: **" + scripts.randomQuote(qEris));
            break;
        case "ives":
        case "master ives":
        case "reef-cryptarch":
        case "the-reef-cryptarch":
        case "reefs-cryptarch":
        case "the-reefs-cryptarch":
            var qIves = require('./assets/ives.js');
            bot.sendMessage(message.channel, "**Master Ives: **" + scripts.randomQuote(qIves));
            break;
        case "mara":
        case "mara-sov":
        case "the-queen":
        case "queen-of-the-reef":
        case "the-queen-of-the-reef":
            var qMara = require('./assets/mara.js');
            bot.sendMessage(message.channel, "**Mara Sov: **" + scripts.randomQuote(qMara));
            break;
        case "osiris":
            var qOsiris = require('./assets/osiris.js');
            bot.sendMessage(message.channel, "**Osiris: **" + scripts.randomQuote(qOsiris));
            break;
        case "petra":
        case "petra-venj":
            var qPetra = require('./assets/petra.js');
            bot.sendMessage(message.channel, "**Petra Venj: **" + scripts.randomQuote(qPetra));
            break;
        case "rahool":
        case "master-rahool":
        case "the-cryptarch":
        case "the-tower-cryptarch":
        case "the-towers-cryptarch":
            var qRahool = require('./assets/rahool.js');
            bot.sendMessage(message.channel, "**Master Rahool: **" + scripts.randomQuote(qRahool));
            break;
        case "shaxx":
        case "lord-shaxx":
            var qShaxx = require("./assets/shaxx.js");
            bot.sendMessage(message.channel, "**Lord Shaxx: **" + scripts.randomQuote(qShaxx));
            break;
        case "saladin":
        case "lord-saladin":
        case "saladin-forge":
        case "forge":
            var qSaladin = require("./assets/saladin.js");
            bot.sendMessage(message.channel, "**Lord Saladin Forge: **" + scripts.randomQuote(qSaladin));
            break;
        case "arcite":
        case "arcite-99-40":
        case "crucible quartermaster":
            var qArcite = require('./assets/arcite.js');
            bot.sendMessage(message.channel, "**Arcite 99-40: **" + scripts.randomQuote(qArcite));
            break;
        case "kadi":
        case "kadi 55-30":
        case "postmaster":
        case "tower postmaster":
        case "vanguard postmaster":
            var qKadi = require('./assets/kadi.js');
            bot.sendMessage(message.channel, "**Kadi 55-30: **" + scripts.randomQuote(qKadi));
        case "list":
        case "show list":
            bot.sendMessage(message.author,
                "**__List of NPC's Currently in My System Followed by How to Call Them__**" +'\n'+
                "_ex:_ `!quotes ives`" +'\n'+'\n'+
                "**The Speaker** - _speaker_ , _the speaker_" +'\n'+
                "**Cayde-6** - _cayde_ , _cayde 6_ , _cayde-6_" +'\n'+
                "**Ikora Rey** - _ikora_ , _ikora rey_ " +'\n'+
                "**Commander Zavala** - _zavala_ , _commander zavala_" +'\n'+
                "**Xur** - _xur_ , _agent of the nine_ , _agent of the 9_ " +'\n'+
                "**Eris Morn** - _eris_ , _eris morn_ " +'\n'+
                "**Master Ives** - _ives_ , _master ives_ , _reef cryptarch_ , _the reef cryptarch_ , _reefs cryptarch_ , _the reefs cryptarch_ " +'\n'+
                "**Mara Sov** - _mara_ , _mara sov_ , _the queen_ , _the queen of the reef_ , _queen of the reef_ " +'\n'+
                "**Osiris** - _osiris_ " +'\n'+
                "**Petra Venj** - _petra venj_ , _petra_ " +'\n'+
                "**Master Rahool** - _master rahool_ , _rahool_ , _the cryptarch_ , _the tower cryptarch_ , _the towers cryptarch_ " +'\n'+
                "**Lore Shaxx** - _lord shaxx_ , _shaxx_ " +'\n'+
                "**Lord Saladin Forge** - _lord saladin_ , _saladin_ , _saladin forge_ , _forge_" +'\n'+
                "**Arcite 99-40** - _arcite_ , _arcite 99-40_ , _crucible quartermaster_" +'\n'+
                "**Kadi 55-30** - _kadi_ , _postmaster_ , _tower postmaster_ , _vanguard postmaster_ " +'\n');
            break;
        default:
            bot.reply(message, "Sorry, either that NPC does not exist or I have not gathered their qoutes just yet. For a listing of supported NPC's issue the following command `!quotes list`.")
    }
}

bot.loginWithToken(process.env.CLIENT_ID, function (token, err) {
    if(err){
        console.log(err);
    }

    bot.once("ready", function() {
        bot.on("message", function (message) {
            var input = message.content;

            var quoteCmd = input.startsWith('!quotes');
            var helpCmd = input.startsWith('!lorehelp');
            var itemCmd = input.startsWith('!item');
            var cardCmd = input.startsWith('!card');
            var siteCmd = input.startsWith('!search');

            if (quoteCmd) { quotes(input,message) };
            if (helpCmd) { help(input, message) };
            if (itemCmd) { searchItems(input, message) };
            if (cardCmd) { searchCard(input, message) };
            if (siteCmd) { searchGrimoire(input, message) };
        });
    });

});<commit_msg>remove commented out lines<commit_after>var scripts = require('./scripts/scripts.js');
var dischord = require('discord.js');
var bot = new dischord.Client({revive: true});

function searchGrimoire(input, message) {

    var stripeCmd = input.substr('8');

    bot.reply(message, "http://www.ishtar-collective.net/search/" + encodeURIComponent(stripeCmd));

}

function searchCard(input, message) {

        var stripeCmd = input.substr('6');
        var query = scripts.normalizeCardInput(stripeCmd);

        bot.reply(message, "http://www.ishtar-collective.net/cards/" + query);

}

function searchItems(input, message) {

        var stripeCmd = input.substr('6');
        var query = scripts.normalizeItemInput(stripeCmd);

        bot.reply(message, "http://www.ishtar-collective.net/items/" + query);

}

function help(input, message) {

    bot.sendMessage(message.author,
        "**LoreBot Help Menu**" +'\n'+'\n'+
        "**__Search Ishtar by Topic__**" +'\n'+
        "**!search** *your search topic*" +'\n'+
        "ex: `!search osiris`" +'\n'+
        "This will return a link such as - ishtar-collective.net/search/osiris" +'\n'+'\n'+
        "**__Search Ishtar for Grimoire Card__**" +'\n'+
        "**!card** *exact name of card you want to show in chat*"+'\n'+
        "ex: `!card osiris`" +'\n'+
        "This will return a link to the card, with first 50 or so characters and image of card. If not, then no card name matched your query. The link provided will still take you to Ishtar and give suggestions based on your query." +'\n'+'\n'+
        "**__Search Ishtar for Item__**" +'\n'+
        "**!item** *item you want to show in chat*" +'\n'+
        "ex: `!item ace of spades`" +'\n'+
        "This will, like the card command, return a link to the item or weapon along with the flavor text and an image of the item. If not, then your search did not match. Follow the link to Ishtar and check if it's suggestions match what you were looking for." +'\n'+'\n'+
        "**__NPC Quotes__**" +'\n'+
        "**!quotes** *the person your wanting the quotes from*" +'\n'+
        "ex: `!quotes mara`" +'\n'+
        "This will return a single random quote from Mara Sov. You can type in Mara, mara, mara sov or queen of the reef, etc to get these quotes." +'\n'+'\n'+
        "**__Display Help Menu__**" +'\n'+
        "`!lorehelp` - Displays this help menu" +'\n'+'\n');

}

/*function paean() {

    bot.on("message", function(message) {
        var input = message.content;
        var help = /(!help)/;
        var paean = /(paean)/i;
        var poster = message.author.id;
        var checkPoster = '159985870458322944';
        var checkForPaean = input.search(paean) != -1;
        var checkForHelp = input.search(help) != -1;
        var memes = [
            "http://sos.campmobile.net/e/2h28ej_g/he7Ud015a309a37y82it_awsowi.jpg",
            "http://sos.campmobile.net/e/2h28ef_6/bbjUd015pzbbt8dfcbse_hsmjp8.jpg",
            "http://sos.campmobile.net/d/2h204b_e/469Ud0151fl3ky5g3fy6u_o6iq9q.jpg",
            "http://sos.campmobile.net/d/2h28cd_d/2d5Ud015psn7vdj6a3wt_l0ky7l.jpg",
            "http://sos.campmobile.net/d/2h068g_i/3e8Ud0158cjt8r6d5mxb_l0ky7l.jpg",
            "https://cdn.discordapp.com/attachments/143886914326495233/186270379533139979/IMG_0800.GIF"
            ]
        var pick = memes[Math.round(Math.random()*(memes.length-1))];
        var name = pick.substr(40, 5);

        breakMyth: if ( checkPoster === poster ) {
            break breakMyth;
        } else if ( checkForPaean ) {
            bot.reply(message, "That does not return any results. But, I have noticed a pattern. Because I am a genius HE HE HE");
            bot.sendFile( message.channel, pick, name + filetype(pick));
        }
    });
}*/

function quotes (input, message) {

    var query = scripts.normalizeItemInput(input.substr('8')).replace(/\s+/g, "-");

    switch (query) {
        case "speaker":
        case "the-speaker":
            var qSpeaker = require('./assets/speaker.js');
            bot.sendMessage(message.channel, "**The Speaker: **" + scripts.randomQuote(qSpeaker));
            break;
        case "cayde":
        case "cayde-6":
            var qCayde = require('./assets/cayde.js');
            bot.sendMessage(message.channel, "**Cayde-6: **" + scripts.randomQuote(qCayde));
            break;
        case "ikora":
        case "ikora-rey":
            var qIkora = require('./assets/ikora.js');
            bot.sendMessage(message.channel, "**Ikora Rey: **" + scripts.randomQuote(qIkora));
            break;
        case "zavala":
        case "commander-zavala":
            var qZavala = require('./assets/zavala.js');
            bot.sendMessage(message.channel, "**Commander Zavala: **" + scripts.randomQuote(qZavala));
            break;
        case "xur":
        case "agent-of-the-nine":
        case "agent-of-the-9":
            var qXur = require('./assets/xur.js');
            bot.sendMessage(message.channel, "**Xur: **" + scripts.randomQuote(qXur));
            break;
        case "eris":
        case "eris-morn":
            var qEris = require('./assets/eris.js');
            bot.sendMessage(message.channel, "**Eris Morn: **" + scripts.randomQuote(qEris));
            break;
        case "ives":
        case "master ives":
        case "reef-cryptarch":
        case "the-reef-cryptarch":
        case "reefs-cryptarch":
        case "the-reefs-cryptarch":
            var qIves = require('./assets/ives.js');
            bot.sendMessage(message.channel, "**Master Ives: **" + scripts.randomQuote(qIves));
            break;
        case "mara":
        case "mara-sov":
        case "the-queen":
        case "queen-of-the-reef":
        case "the-queen-of-the-reef":
            var qMara = require('./assets/mara.js');
            bot.sendMessage(message.channel, "**Mara Sov: **" + scripts.randomQuote(qMara));
            break;
        case "osiris":
            var qOsiris = require('./assets/osiris.js');
            bot.sendMessage(message.channel, "**Osiris: **" + scripts.randomQuote(qOsiris));
            break;
        case "petra":
        case "petra-venj":
            var qPetra = require('./assets/petra.js');
            bot.sendMessage(message.channel, "**Petra Venj: **" + scripts.randomQuote(qPetra));
            break;
        case "rahool":
        case "master-rahool":
        case "the-cryptarch":
        case "the-tower-cryptarch":
        case "the-towers-cryptarch":
            var qRahool = require('./assets/rahool.js');
            bot.sendMessage(message.channel, "**Master Rahool: **" + scripts.randomQuote(qRahool));
            break;
        case "shaxx":
        case "lord-shaxx":
            var qShaxx = require("./assets/shaxx.js");
            bot.sendMessage(message.channel, "**Lord Shaxx: **" + scripts.randomQuote(qShaxx));
            break;
        case "saladin":
        case "lord-saladin":
        case "saladin-forge":
        case "forge":
            var qSaladin = require("./assets/saladin.js");
            bot.sendMessage(message.channel, "**Lord Saladin Forge: **" + scripts.randomQuote(qSaladin));
            break;
        case "arcite":
        case "arcite-99-40":
        case "crucible quartermaster":
            var qArcite = require('./assets/arcite.js');
            bot.sendMessage(message.channel, "**Arcite 99-40: **" + scripts.randomQuote(qArcite));
            break;
        case "kadi":
        case "kadi 55-30":
        case "postmaster":
        case "tower postmaster":
        case "vanguard postmaster":
            var qKadi = require('./assets/kadi.js');
            bot.sendMessage(message.channel, "**Kadi 55-30: **" + scripts.randomQuote(qKadi));
        case "list":
        case "show list":
            bot.sendMessage(message.author,
                "**__List of NPC's Currently in My System Followed by How to Call Them__**" +'\n'+
                "_ex:_ `!quotes ives`" +'\n'+'\n'+
                "**The Speaker** - _speaker_ , _the speaker_" +'\n'+
                "**Cayde-6** - _cayde_ , _cayde 6_ , _cayde-6_" +'\n'+
                "**Ikora Rey** - _ikora_ , _ikora rey_ " +'\n'+
                "**Commander Zavala** - _zavala_ , _commander zavala_" +'\n'+
                "**Xur** - _xur_ , _agent of the nine_ , _agent of the 9_ " +'\n'+
                "**Eris Morn** - _eris_ , _eris morn_ " +'\n'+
                "**Master Ives** - _ives_ , _master ives_ , _reef cryptarch_ , _the reef cryptarch_ , _reefs cryptarch_ , _the reefs cryptarch_ " +'\n'+
                "**Mara Sov** - _mara_ , _mara sov_ , _the queen_ , _the queen of the reef_ , _queen of the reef_ " +'\n'+
                "**Osiris** - _osiris_ " +'\n'+
                "**Petra Venj** - _petra venj_ , _petra_ " +'\n'+
                "**Master Rahool** - _master rahool_ , _rahool_ , _the cryptarch_ , _the tower cryptarch_ , _the towers cryptarch_ " +'\n'+
                "**Lore Shaxx** - _lord shaxx_ , _shaxx_ " +'\n'+
                "**Lord Saladin Forge** - _lord saladin_ , _saladin_ , _saladin forge_ , _forge_" +'\n'+
                "**Arcite 99-40** - _arcite_ , _arcite 99-40_ , _crucible quartermaster_" +'\n'+
                "**Kadi 55-30** - _kadi_ , _postmaster_ , _tower postmaster_ , _vanguard postmaster_ " +'\n');
            break;
        default:
            bot.reply(message, "Sorry, either that NPC does not exist or I have not gathered their qoutes just yet. For a listing of supported NPC's issue the following command `!quotes list`.")
    }
}

bot.loginWithToken(process.env.CLIENT_ID, function (token, err) {
    if(err){
        console.log(err);
    }

    bot.once("ready", function() {
        bot.on("message", function (message) {
            var input = message.content;

            var quoteCmd = input.startsWith('!quotes');
            var helpCmd = input.startsWith('!lorehelp');
            var itemCmd = input.startsWith('!item');
            var cardCmd = input.startsWith('!card');
            var siteCmd = input.startsWith('!search');

            if (quoteCmd) { quotes(input,message) };
            if (helpCmd) { help(input, message) };
            if (itemCmd) { searchItems(input, message) };
            if (cardCmd) { searchCard(input, message) };
            if (siteCmd) { searchGrimoire(input, message) };
        });
    });

});<|endoftext|>


<commit_before>async function waitUntilElementFound(page, elementSelector, onlyVisible = false, timeout = 30000) {
  await page.waitForSelector(elementSelector, { visible: onlyVisible, timeout });
}

async function fillInput(page, inputSelector, inputValue) {
  await page.$eval(inputSelector, (input) => {
    const inputElement = input;
    inputElement.value = '';
  });
  await page.type(inputSelector, inputValue);
}

async function clickButton(page, buttonSelector) {
  await page.$eval(buttonSelector, el => el.click());
}

async function pageEvalAll(page, selector, defaultResult, callback) {
  let result = defaultResult;
  try {
    result = await page.$$eval(selector, callback);
  } catch (e) {
    // TODO temporary workaround to puppeteer@1.5.0 which breaks $$eval bevahvior until they will release a new version.
    if (e.message.indexOf('Error: failed to find elements matching selector') !== 0) {
      throw e;
    }
  }

  return result;
}

async function elementPresentOnPage(page, selector) {
  return await page.$(selector) !== null;
}

async function dropdownSelect(page, selectSelector, value) {
  await page.select(selectSelector, value);
}

async function dropdownElements(page, selector) {
  const options = await page.evaluate((optionSelector) => {
    return Array.from(document.querySelectorAll(optionSelector))
      .filter(o => o.value)
      .map((o) => {
        return {
          name: o.text,
          value: o.value,
        };
      });
  }, `${selector} > option`);
  return options;
}

export {
  waitUntilElementFound,
  fillInput,
  clickButton,
  dropdownSelect,
  dropdownElements,
  pageEvalAll,
  elementPresentOnPage,
};
<commit_msg>Revert "Use page.$eval"<commit_after>async function waitUntilElementFound(page, elementSelector, onlyVisible = false, timeout = 30000) {
  await page.waitForSelector(elementSelector, { visible: onlyVisible, timeout });
}

async function fillInput(page, inputSelector, inputValue) {
  await page.$eval(inputSelector, (input) => {
    const inputElement = input;
    inputElement.value = '';
  });
  await page.type(inputSelector, inputValue);
}

async function clickButton(page, buttonSelector) {
  const button = await page.$(buttonSelector);
  await button.click();
}

async function pageEvalAll(page, selector, defaultResult, callback) {
  let result = defaultResult;
  try {
    result = await page.$$eval(selector, callback);
  } catch (e) {
    // TODO temporary workaround to puppeteer@1.5.0 which breaks $$eval bevahvior until they will release a new version.
    if (e.message.indexOf('Error: failed to find elements matching selector') !== 0) {
      throw e;
    }
  }

  return result;
}

async function elementPresentOnPage(page, selector) {
  return await page.$(selector) !== null;
}

async function dropdownSelect(page, selectSelector, value) {
  await page.select(selectSelector, value);
}

async function dropdownElements(page, selector) {
  const options = await page.evaluate((optionSelector) => {
    return Array.from(document.querySelectorAll(optionSelector))
      .filter(o => o.value)
      .map((o) => {
        return {
          name: o.text,
          value: o.value,
        };
      });
  }, `${selector} > option`);
  return options;
}

export {
  waitUntilElementFound,
  fillInput,
  clickButton,
  dropdownSelect,
  dropdownElements,
  pageEvalAll,
  elementPresentOnPage,
};
<|endoftext|>


<commit_before>var Bot = require('ttapi');
var AUTH= process.env.PRABBAUTH;
var USERID= process.env.PRABBUSERID;
var ROOM= process.env.PRABBROOM;

var bot = new Bot(AUTH, USERID, ROOM);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var Dj = mongoose.model("Dj", require("./models/dj").Dj);
var Track = mongoose.model("Track", require("./models/track").Track);
var Artist = mongoose.model("Artist", require("./models/artist").Artist);
var Play = mongoose.model("Play", require("./models/play").Play);

var twitter = require('./tweets').twitter;

var currentSong;

bot.on('newsong', function(data){
  setCurrentSong(data);
  show_link(data.room.metadata.current_song.metadata.artist);
  tweet_song(data.room.metadata.current_song.metadata.artist);
});
show_link = function(artist){
    var response = artist + ' Info: ';
    response+="http://www.postrockandbeyond.com/artists/";
    response+=escape(artist);
    bot.speak(response);
};
bot.on('ready', function(data){
  bot.roomInfo(function(data){
    setCurrentSong(data);
  });
});

bot.on('update_votes', function(data){
  currentSong.upvotes= data.room.metadata.upvotes;
  currentSong.downvotes= data.room.metadata.downvotes;
  currentSong.listeners= data.room.metadata.listeners;
  currentSong.save(function(err){log_error(err);});
});

bot.on('endsong', function(){
  updatePlayInfo();
});
bot.on('add_dj', function(data){
  Dj.find_or_create_by_userid(data.user[0].userid, data.user[0].name, new Dj(), function(err, docs){
        log_error(err);
  });
});

bot.on('speak', function(data){
  Dj.isAdmin(data.userid, function(err, res){
    log_error(err);
    if(res){
      var result = data.text.match(/^\/(.*?)( .*)?$/);
      if(result){
        var command = result[1].trim().toLowerCase();
        var param = '';
        if (result.length == 3 && result[2]){
          param = result[2].trim().toLowerCase();
        }

        switch(command){
          case 'sa':
          case 'setadmin':
            setAdmin(param);
            break;
          case 'da':
          case 'deladmin':
            deleteAdmin(param);
            break;

          case 'sb':
          case 'setbandcamp':
            setLink('bandcamp', param);
            break;
          case 'db':
          case 'delbandcamp':
            deleteLink('bandcamp');
            break;
          case 'sf':
          case 'setfacebook':
            setLink('facebook', param);
            break;
          case 'df':
          case 'delfacebook':
            deleteLink('facebook');
            break;
          case 'sw':
          case 'setwebsite':
            setLink('website', param);
            break;
          case 'dw':
          case 'delwebsite':
            deleteLink('website');
            break;
          case 'sfm':
          case 'setlast':
            setLink('lastfm', param);
            break;
          case 'dfm':
          case 'dellast':
            deleteLink('lastfm');
            break;
          case 'sl':
            show_link(currentSong.artist.name);
            break;
          case 'tweet':
            tweet_song(currentSong.artist.name);
            break;
        }
      }
    }
  });
});

tweet_song = function(artist){
  var status = "Now playing #"+artist.toLowerCase().replace(/\ /gi,"")+" in http://turntable.fm/postrock_beyond"
  twitter.verifyCredentials(function(){}).updateStatus(status, function(){});
};

deleteAdmin = function(name){
  bot.getProfile(name, function(data){
    Dj.update({userid: data.userid},{admin: false},function(err, docs){
      log_error();
      bot.speak(name + ' is no longer an admin.');
    });
  });
};

setAdmin = function(name){
  bot.getProfile(name, function(data){
    Dj.update({userid: data.userid},{admin: true},function(err, docs){
      bot.speak(name + ' added as an admin.');
    });
  });
};

deleteLink = function(key){
  if(key && currentSong){
    currentSong.artist.links[key] = '';
    artist = currentSong.artist;
    artist.save(function(err){log_error();});
    bot.speak("Removed "+key+" link");
  }else{console.log(key,currentSong);}
};

setLink = function(key, value){
  if(key && value && currentSong){
    currentSong.artist.links[key] = value;
    artist = currentSong.artist;
    artist.save(function(err){log_error();});
    bot.speak("Added "+key+" link: "+value);
  }else{console.log(key, value, currentSong);}
};

setCurrentSong = function(data){
  if(data.room.metadata.current_song){
  song = data.room.metadata.current_song;
  dj = data.room.metadata.current_dj;
  upvotes = data.room.metadata.upvotes;
  downvotes = data.room.metadata.downvotes;
  listeners = data.room.metadata.listeners;

  bot.getProfile(dj, function(data){
    Dj.find_or_create_by_userid(dj,data.name,new Dj(), function(err, docs){
      log_error(err);
      var dj = docs;
      Artist.find_or_create_by_name(song.metadata.artist, song, new Artist(), function(err, docs){
        log_error(err);
        var artist = docs;
        Track.find_or_create_by_name(song.metadata.song, song.metadata.album, artist.id, new Track(), function(err, docs){
          log_error(err);
          var track = docs;
          artist.tracks.push(track.id);
          artist.save(function(err){log_error(err);});
          Play.find_or_create_by_timestamp(song.starttime, dj.id, artist.id, track.id, new Play(), function(err, docs){
            currentSong = docs;
            currentSong.upvotes = upvotes;
            currentSong.downvotes = downvotes;
            currentSong.listeners = listeners;
          });
        });
      });
    });
  });
  }
};

updatePlayInfo = function(){
  currentSong.dj.plays++;
  currentSong.dj.upvotes = currentSong.dj.upvotes ? currentSong.dj.upvotes+currentSong.upvotes : currentSong.upvotes;
  currentSong.dj.downvotes = currentSong.dj.downvotes ? currentSong.dj.downvotes+currentSong.downvotes : currentSong.downvotes;
  dj = currentSong.dj;
  dj.save(function(err){log_error(err);});

  currentSong.artist.plays = currentSong.artist.plays ? currentSong.artist.plays+1 : 1;
  currentSong.artist.upvotes = currentSong.artist.upvotes ? currentSong.artist.upvotes+currentSong.upvotes : currentSong.upvotes;
  currentSong.artist.downvotes = currentSong.artist.downvotes ? currentSong.artist.downvotes+currentSong.downvotes : currentSong.downvotes;
  artist = currentSong.artist;
  artist.save(function(err){log_error(err);});

  currentSong.track.plays = currentSong.track.plays ? currentSong.track.plays+1:1;
  currentSong.track.upvotes = currentSong.track.upvotes ? currentSong.track.upvotes+currentSong.upvotes : currentSong.upvotes;
  currentSong.track.downvotes = currentSong.track.downvotes ? currentSong.track.downvotes+currentSong.downvotes : currentSong.downvotes;
  track = currentSong.track;
  track.save(function(err){log_error(err);});
  currentSong.save(function(err){log_error(err);});
};
log_error = function(err){
  if(err){
    console.log(err);
  }
};
exports.bot = bot;
<commit_msg>Adding another hash tag to the tweet<commit_after>var Bot = require('ttapi');
var AUTH= process.env.PRABBAUTH;
var USERID= process.env.PRABBUSERID;
var ROOM= process.env.PRABBROOM;

var bot = new Bot(AUTH, USERID, ROOM);
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var Dj = mongoose.model("Dj", require("./models/dj").Dj);
var Track = mongoose.model("Track", require("./models/track").Track);
var Artist = mongoose.model("Artist", require("./models/artist").Artist);
var Play = mongoose.model("Play", require("./models/play").Play);

var twitter = require('./tweets').twitter;

var currentSong;

bot.on('newsong', function(data){
  setCurrentSong(data);
  show_link(data.room.metadata.current_song.metadata.artist);
  tweet_song(data.room.metadata.current_song.metadata.artist);
});
show_link = function(artist){
    var response = artist + ' Info: ';
    response+="http://www.postrockandbeyond.com/artists/";
    response+=escape(artist);
    bot.speak(response);
};
bot.on('ready', function(data){
  bot.roomInfo(function(data){
    setCurrentSong(data);
  });
});

bot.on('update_votes', function(data){
  currentSong.upvotes= data.room.metadata.upvotes;
  currentSong.downvotes= data.room.metadata.downvotes;
  currentSong.listeners= data.room.metadata.listeners;
  currentSong.save(function(err){log_error(err);});
});

bot.on('endsong', function(){
  updatePlayInfo();
});
bot.on('add_dj', function(data){
  Dj.find_or_create_by_userid(data.user[0].userid, data.user[0].name, new Dj(), function(err, docs){
        log_error(err);
  });
});

bot.on('speak', function(data){
  Dj.isAdmin(data.userid, function(err, res){
    log_error(err);
    if(res){
      var result = data.text.match(/^\/(.*?)( .*)?$/);
      if(result){
        var command = result[1].trim().toLowerCase();
        var param = '';
        if (result.length == 3 && result[2]){
          param = result[2].trim().toLowerCase();
        }

        switch(command){
          case 'sa':
          case 'setadmin':
            setAdmin(param);
            break;
          case 'da':
          case 'deladmin':
            deleteAdmin(param);
            break;

          case 'sb':
          case 'setbandcamp':
            setLink('bandcamp', param);
            break;
          case 'db':
          case 'delbandcamp':
            deleteLink('bandcamp');
            break;
          case 'sf':
          case 'setfacebook':
            setLink('facebook', param);
            break;
          case 'df':
          case 'delfacebook':
            deleteLink('facebook');
            break;
          case 'sw':
          case 'setwebsite':
            setLink('website', param);
            break;
          case 'dw':
          case 'delwebsite':
            deleteLink('website');
            break;
          case 'sfm':
          case 'setlast':
            setLink('lastfm', param);
            break;
          case 'dfm':
          case 'dellast':
            deleteLink('lastfm');
            break;
          case 'sl':
            show_link(currentSong.artist.name);
            break;
          case 'tweet':
            tweet_song(currentSong.artist.name);
            break;
        }
      }
    }
  });
});

tweet_song = function(artist){
  var status = "Now playing #"+artist.toLowerCase().replace(/\ /gi,"")+" in http://turntable.fm/postrock_beyond #turntablefm"
  twitter.verifyCredentials(function(){}).updateStatus(status, function(){});
};

deleteAdmin = function(name){
  bot.getProfile(name, function(data){
    Dj.update({userid: data.userid},{admin: false},function(err, docs){
      log_error();
      bot.speak(name + ' is no longer an admin.');
    });
  });
};

setAdmin = function(name){
  bot.getProfile(name, function(data){
    Dj.update({userid: data.userid},{admin: true},function(err, docs){
      bot.speak(name + ' added as an admin.');
    });
  });
};

deleteLink = function(key){
  if(key && currentSong){
    currentSong.artist.links[key] = '';
    artist = currentSong.artist;
    artist.save(function(err){log_error();});
    bot.speak("Removed "+key+" link");
  }else{console.log(key,currentSong);}
};

setLink = function(key, value){
  if(key && value && currentSong){
    currentSong.artist.links[key] = value;
    artist = currentSong.artist;
    artist.save(function(err){log_error();});
    bot.speak("Added "+key+" link: "+value);
  }else{console.log(key, value, currentSong);}
};

setCurrentSong = function(data){
  if(data.room.metadata.current_song){
  song = data.room.metadata.current_song;
  dj = data.room.metadata.current_dj;
  upvotes = data.room.metadata.upvotes;
  downvotes = data.room.metadata.downvotes;
  listeners = data.room.metadata.listeners;

  bot.getProfile(dj, function(data){
    Dj.find_or_create_by_userid(dj,data.name,new Dj(), function(err, docs){
      log_error(err);
      var dj = docs;
      Artist.find_or_create_by_name(song.metadata.artist, song, new Artist(), function(err, docs){
        log_error(err);
        var artist = docs;
        Track.find_or_create_by_name(song.metadata.song, song.metadata.album, artist.id, new Track(), function(err, docs){
          log_error(err);
          var track = docs;
          artist.tracks.push(track.id);
          artist.save(function(err){log_error(err);});
          Play.find_or_create_by_timestamp(song.starttime, dj.id, artist.id, track.id, new Play(), function(err, docs){
            currentSong = docs;
            currentSong.upvotes = upvotes;
            currentSong.downvotes = downvotes;
            currentSong.listeners = listeners;
          });
        });
      });
    });
  });
  }
};

updatePlayInfo = function(){
  currentSong.dj.plays++;
  currentSong.dj.upvotes = currentSong.dj.upvotes ? currentSong.dj.upvotes+currentSong.upvotes : currentSong.upvotes;
  currentSong.dj.downvotes = currentSong.dj.downvotes ? currentSong.dj.downvotes+currentSong.downvotes : currentSong.downvotes;
  dj = currentSong.dj;
  dj.save(function(err){log_error(err);});

  currentSong.artist.plays = currentSong.artist.plays ? currentSong.artist.plays+1 : 1;
  currentSong.artist.upvotes = currentSong.artist.upvotes ? currentSong.artist.upvotes+currentSong.upvotes : currentSong.upvotes;
  currentSong.artist.downvotes = currentSong.artist.downvotes ? currentSong.artist.downvotes+currentSong.downvotes : currentSong.downvotes;
  artist = currentSong.artist;
  artist.save(function(err){log_error(err);});

  currentSong.track.plays = currentSong.track.plays ? currentSong.track.plays+1:1;
  currentSong.track.upvotes = currentSong.track.upvotes ? currentSong.track.upvotes+currentSong.upvotes : currentSong.upvotes;
  currentSong.track.downvotes = currentSong.track.downvotes ? currentSong.track.downvotes+currentSong.downvotes : currentSong.downvotes;
  track = currentSong.track;
  track.save(function(err){log_error(err);});
  currentSong.save(function(err){log_error(err);});
};
log_error = function(err){
  if(err){
    console.log(err);
  }
};
exports.bot = bot;
<|endoftext|>


<commit_before>// @flow
import _ from 'lodash';
import Bluebird from 'bluebird';
import Store from '../interfaces/store';
import Common from '../classes/common';

export default class Mysql extends Common implements Store {
  buckets: {};
  transaction: Array<any>;

  constructor(db, options) {
    super();
    this.buckets = ['meta', 'parents', 'permissions', 'resources', 'roles', 'users'];
    this.options = _.defaults({}, options, {prefix: ''});
    this.db = this.setup(db, this.options);
  }

  /**
   * @description Begins a transaction.
   * @returns {Array.<any>}
   */
  begin() {
    // Returns a transaction object
    this.transaction = [];
    return this.transaction;
  }

  /**
   * @description Ends a transaction (and executes it).
   * @param cb
   */
  end(cb) {
    // Execute transaction
    return Bluebird.reduce(this.transaction, (res, func) => func(), null)
      .then()
      .nodeify(cb);
  }

  /**
   * @description Cleans the whole storage.
   * @param cb
   */
  clean(cb) {
    return this.setup().clean(this.db, this.options).nodeify(cb);
  }

  /**
   * @description Gets the contents at the bucket's key.
   * @param bucket
   * @param key
   * @param cb
   */
  get(bucket, key, cb) {
    return this.findRow(bucket, key)
      .then((row) => {
        if (!row) return [];
        if (bucket.indexOf('allows_') === 0) return this.getPermission(key, row);
        return row.value;
      })
      .nodeify(cb);
  }

  /**
   * @description Returns the union of the values in the given keys.
   * @param bucket
   * @param keys
   * @param cb
   */
  union(bucket, keys, cb) {
    return this.findRows(bucket, keys)
      .then((rows) => {
        if (bucket.indexOf('allows_') === 0) return this.getPermission(keys, rows);
        return _.union.apply(_, rows.map((row) => row.value));
      })
      .nodeify(cb);
  }

  /**
   * @description Adds values to a given key inside a bucket.
   * @param bucket
   * @param key
   * @param values
   */
  add(bucket, key, values) {
    const valuesTmp = Array.isArray(values) ? values : [values];
    let bucketTmp = bucket;
    let keyTmp = key;
    this.transaction.push(() => {
      return this.findRow(bucketTmp, keyTmp)
        .then((row) => {
          let update;
          if (bucketTmp.indexOf('allows_') === 0) {
            update = (row && row.value) ? row.value : {};
            update[keyTmp] = _.union(update[keyTmp], valuesTmp);
            keyTmp = bucketTmp;
            bucketTmp = 'permissions';
          } else {
            update = _.union(row && row.value, valuesTmp);
          }
          return this.getModel(bucketTmp).upsert({key: keyTmp, value: JSON.stringify(update)});
        });
    });
  }

  /**
   * @description Delete the given key(s) at the bucket
   * @param bucket
   * @param keys
   */
  del(bucket, keys) {
    const keysTmp = Array.isArray(keys) ? keys : [keys];

    this.transaction.push(() => {
      if (bucket.indexOf('allows_') === 0) {
        return this.findRow(bucket)
          .then((row) => {
            if (!row) return;
            const update = row.value;
            keysTmp.forEach((key) => {
              update[key] = undefined;
            });
            row.set('value', JSON.stringify(update)).save();
          });
      }
      return this.getModel(bucket)
        .destroy({where: {key: {$in: keysTmp}}});
    });
  }

  /**
   * @description Removes values from a given key inside a bucket.
   * @param bucket
   * @param key
   * @param values
   */
  remove(bucket, key, values) {
    const valuesTmp = Array.isArray(values) ? values : [values];

    this.transaction.push(() => {
      return this.findRow(bucket, key)
        .then((row) => {
          let update;
          if (!row) return;
          if (bucket.indexOf('allows_') === 0) {
            update = row.value;
            update[key] = _.difference(update[key], valuesTmp);
          } else {
            update = _.difference(row.value, valuesTmp);
          }
          row.value = JSON.stringify(update);
          row.save();
        });
    });
  }

  /**
   * @description Setup database.
   * @param db
   * @param options
   * @returns {*}
   */
  setup(db, options) {
    const {prefix} = options;
    const schema = options.schema || {};
    const defaultSchema = options.defaultSchema || {
      key: {type: db.Sequelize.STRING, primaryKey: true},
      value: {type: db.Sequelize.STRING},
    };

    this.buckets.forEach((table) => {
      const name = prefix + table;
      if (!db.models[name]) db.define(name, schema[table] || defaultSchema).sync();
    });
    return db;
  }

  /**
   * @description Returns model for bucket.
   * @param bucket
   * @returns {*}
   */
  getModel(bucket) {
    return this.db.models[this.options.prefix + bucket];
  }

  /**
   * @description Returns values for permissions bucket
   * @param keys
   * @param row
   * @returns {*}
   */
  getPermission(keys, row) {
    const res = (row && row.value) ? row.value : {};
    const keysTmp = Array.isArray(keys) ? keys : [keys];
    return _.union.apply(_, keysTmp.map((key) => res[key] || []));
  }

  /**
   * @description Find the row for specific bucket.
   * @param bucket
   * @param key
   * @returns {Promise}
   */
  findRow(bucket, key) {
    let bucketTmp = bucket;
    let keyTmp = key;
    let perm = false;

    if (bucketTmp.indexOf('allows_') === 0) {
      keyTmp = bucketTmp;
      bucketTmp = 'permissions';
      perm = true;
    }

    return this.getModel(bucketTmp)
      .findOne({where: {key: keyTmp.toString()}, attributes: ['key', 'value']})
      .then((row) => {
        if (!row) return null;
        row.value = row.value && JSON.parse(row.value) || (perm ? {} : []);
        return row;
      });
  }

  /**
   * @description Find the row for specific bucket.
   * @param bucket
   * @param keys
   * @returns {Promise}
   */
  findRows(bucket, keys) {
    if (bucket.indexOf('allows_') === 0) return this.findRow(bucket);
    return this.getModel(bucket)
      .findAll({where: {key: {$in: keys.map((key) => key.toString())}}, attributes: ['key', 'value']})
      .then((rows) => {
        return rows.map((row) => {
          row.value = (row.value && JSON.parse(row.value)) ? row.value = JSON.parse(row.value) : [];
          return row;
        });
      });
  }
}
<commit_msg>refact(stores/mysql.js) eslint compliant<commit_after>// @flow
import _ from 'lodash';
import Bluebird from 'bluebird';
import Store from '../interfaces/store';
import Common from '../classes/common';

export default class MySQL extends Common implements Store {
  buckets: {};
  transaction: Array<any>;

  constructor(db, options) {
    super();
    this.buckets = ['meta', 'parents', 'permissions', 'resources', 'roles', 'users'];
    this.options = _.defaults({}, options, {prefix: ''});
    this.db = this.setup(db, this.options);
  }

  /**
   * @description Begins a transaction.
   * @returns {Array.<any>}
   */
  begin(): Array<any> {
    // Returns a transaction object
    this.transaction = [];
    return this.transaction;
  }

  /**
   * @description Ends a transaction (and executes it).
   * @param cb
   * @returns {*}
   */
  end(cb): any {
    // Execute transaction
    return Bluebird.reduce(this.transaction, (res, func) => func(), null)
      .then()
      .nodeify(cb);
  }

  /**
   * @description Cleans the whole storage.
   * @param cb
   * @returns {*}
   */
  clean(cb): any {
    return this.setup().clean(this.db, this.options).nodeify(cb);
  }

  /**
   * @description Gets the contents at the bucket's key.
   * @param bucket
   * @param key
   * @param cb
   * @returns {*}
   */
  get(bucket, key, cb): any {
    return this.findRow(bucket, key)
      .then((row) => {
        if (!row) return [];
        if (bucket.indexOf('allows_') === 0) return MySQL.getPermission(key, row);
        return row.value;
      })
      .nodeify(cb);
  }

  /**
   * @description Returns the union of the values in the given keys.
   * @param bucket
   * @param keys
   * @param cb
   */
  union(bucket, keys, cb): any {
    return this.findRows(bucket, keys)
      .then((rows) => {
        if (bucket.indexOf('allows_') === 0) return MySQL.getPermission(keys, rows);
        return _.union(...rows.map((row) => row.value));
      })
      .nodeify(cb);
  }

  /**
   * @description Adds values to a given key inside a bucket.
   * @param bucket
   * @param key
   * @param values
   */
  add(bucket, key, values) {
    const valuesTmp = Array.isArray(values) ? values : [values];
    let bucketTmp = bucket;
    let keyTmp = key;
    this.transaction.push(() => this.findRow(bucketTmp, keyTmp)
      .then((row) => {
        let update;
        if (bucketTmp.indexOf('allows_') === 0) {
          update = (row && row.value) ? row.value : {};
          update[keyTmp] = _.union(update[keyTmp], valuesTmp);
          keyTmp = bucketTmp;
          bucketTmp = 'permissions';
        } else {
          update = _.union(row && row.value, valuesTmp);
        }
        return this.getModel(bucketTmp).upsert({key: keyTmp, value: JSON.stringify(update)});
      }));
  }

  /**
   * @description Delete the given key(s) at the bucket
   * @param bucket
   * @param keys
   */
  del(bucket, keys) {
    const keysTmp = Array.isArray(keys) ? keys : [keys];

    this.transaction.push(() => {
      if (bucket.indexOf('allows_') === 0) {
        return this.findRow(bucket)
          .then((row) => {
            if (!row) return;
            const update = row.value;
            keysTmp.forEach((key) => {
              update[key] = undefined;
            });
            row.set('value', JSON.stringify(update)).save();
          });
      }
      return this.getModel(bucket)
        .destroy({where: {key: {$in: keysTmp}}});
    });
  }

  /**
   * @description Removes values from a given key inside a bucket.
   * @param bucket
   * @param key
   * @param values
   */
  remove(bucket, key, values) {
    const valuesTmp = Array.isArray(values) ? values : [values];

    this.transaction.push(() => this.findRow(bucket, key)
      .then((row) => {
        let update;
        if (!row) return;
        if (bucket.indexOf('allows_') === 0) {
          update = row.value;
          update[key] = _.difference(update[key], valuesTmp);
        } else {
          update = _.difference(row.value, valuesTmp);
        }
        const rowTmp = row;
        rowTmp.value = JSON.stringify(update);
        rowTmp.save();
      }));
  }

  /**
   * @description Setup database.
   * @param db
   * @param options
   * @returns {*}
   */
  setup(db, options): {} {
    const {prefix} = options;
    const schema = options.schema || {};
    const defaultSchema = options.defaultSchema || {
      key: {type: db.Sequelize.STRING, primaryKey: true},
      value: {type: db.Sequelize.STRING},
    };

    this.buckets.forEach((table) => {
      const name = prefix + table;
      if (!db.models[name]) db.define(name, schema[table] || defaultSchema).sync();
    });
    return db;
  }

  /**
   * @description Returns model for bucket.
   * @param bucket
   * @returns {*}
   */
  getModel(bucket): {} {
    return this.db.models[this.options.prefix + bucket];
  }

  /**
   * @description Find the row for specific bucket.
   * @param bucket
   * @param key
   * @returns {Promise}
   */
  findRow(bucket, key): {} {
    let bucketTmp = bucket;
    let keyTmp = key;
    let perm = false;

    if (bucketTmp.indexOf('allows_') === 0) {
      keyTmp = bucketTmp;
      bucketTmp = 'permissions';
      perm = true;
    }

    return this.getModel(bucketTmp)
      .findOne({where: {key: keyTmp.toString()}, attributes: ['key', 'value']})
      .then((row) => {
        if (!row) return null;
        const rowTmp = row;

        if (row.value && JSON.parse(row.value)) {
          rowTmp.value = JSON.parse(row.value);
        } else {
          rowTmp.value = perm ? {} : [];
        }
        return rowTmp;
      });
  }

  /**
   * @description Find the row for specific bucket.
   * @param bucket
   * @param keys
   * @returns {Promise}
   */
  findRows(bucket, keys): Array<any> {
    if (bucket.indexOf('allows_') === 0) return this.findRow(bucket);
    return this.getModel(bucket)
      .findAll({where: {key: {$in: keys.map((key) => key.toString())}}, attributes: ['key', 'value']})
      .then((rows) => rows.map((row) => {
        const rowTmp = row;
        if (row.value && JSON.parse(row.value)) {
          rowTmp.value = JSON.parse(row.value);
        } else {
          rowTmp.value = [];
        }
        return row;
      }));
  }

  /**
   * @description Returns values for permissions bucket
   * @param keys
   * @param row
   * @returns {*}
   */
  static getPermission(keys, row): Array<any> {
    const res = (row && row.value) ? row.value : {};
    const keysTmp = Array.isArray(keys) ? keys : [keys];
    return _.union(...keysTmp.map((key) => res[key] || []));
  }
}
<|endoftext|>


<commit_before>/**
 * @file Rhino specific stream implementation
 * @since 0.2.1
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfStreamSecureRead*/ // Generate a wrapper to secure multiple calls to stream#read
/*global _gpfStreamSecureWrite*/ // Generates a wrapper to secure multiple calls to stream#write
/*exported _GpfRhinoBaseStream*/ // gpf.rhino.BaseStream
/*exported _GpfRhinoReadableStream*/ // gpf.rhino.ReadableStream
/*exported _GpfRhinoWritableStream*/ // gpf.rhino.WritableStream
/*#endif*/

/*jshint rhino: true*/
/*eslint-env rhino*/

var
    _GpfRhinoBaseStream = _gpfDefine(/** @lends gpf.rhino.BaseStream.prototype */ {
        $class: "gpf.rhino.BaseStream",

        /**
         * Base class wrapping Rhino streams
         *
         * @param {java.io.InputStream|java.io.OutputStream} stream Rhino input or output stream object
         *
         * @constructor gpf.rhino.BaseStream
         * @private
         * @since 0.2.1
         */
        constructor: function (stream) {
            this._stream = stream;
        },

        /**
         * Close the stream
         *
         * @return {Promise} Resolved when closed
         * @since 0.2.1
         */
        close: function () {
            this._stream.close();
            return Promise.resolve();
        },

        /**
         * Rhino stream object
         *
         * @type {java.io.InputStream|java.io.OutputStream}
         * @since 0.2.1
         */
        _stream: null

    }),

    /**
     * Wraps a readable stream from Rhino into a IReadableStream
     *
     * @param {java.io.InputStream} stream Rhino stream object
     *
     * @class gpf.rhino.ReadableStream
     * @extends gpf.rhino.BaseStream
     * @implements {gpf.interfaces.IReadableStream}
     * @since 0.2.1
     */
    _GpfRhinoReadableStream = _gpfDefine(/** @lends gpf.rhino.ReadableStream.prototype */ {
        $class: "gpf.rhino.ReadableStream",
        $extend: "gpf.rhino.BaseStream",

        //region gpf.interfaces.IReadableStream

        /**
         * Process error that occurred during the stream reading
         *
         * @param {Error} e Error coming from read
         * @return {Promise} Read result replacement
         * @since 0.2.1
         */
        _handleError: function (e) {
            if (e.message.indexOf("java.util.NoSuchElementException") === 0) {
                // Empty stream
                return Promise.resolve();
            }
            return Promise.reject(e);
        },

        /**
         * @gpf:sameas gpf.interfaces.IReadableStream#read
         * @since 0.2.1
         */
        read: _gpfStreamSecureRead(function (output) {
            try {
                var scanner = new java.util.Scanner(this._stream); //eslint-disable-line no-invalid-this
                return output.write(String(scanner.useDelimiter("\\A").next()));
            } catch (e) {
                return this._handleError(e); //eslint-disable-line no-invalid-this
            }
        })

        //endregion

    }),

    /**
     * Wraps a writable stream from Rhino into a IWritableStream
     *
     * @param {java.io.OutputStream} stream Rhino stream object
     *
     * @class gpf.rhino.WritableStream
     * @extends gpf.rhino.BaseStream
     * @implements {gpf.interfaces.IWritableStream}
     * @since 0.2.1
     */
    _GpfRhinoWritableStream = _gpfDefine(/** @lends gpf.rhino.WritableStream.prototype */ {
        $class: "gpf.rhino.WritableStream",
        $extend: "gpf.rhino.BaseStream",

        constructor: function (stream) {
            this.$super(stream);
            this._writer = new java.io.OutputStreamWriter(stream);
        },

        //region gpf.interfaces.IWritableStream

        /**
         * @gpf:sameas gpf.interfaces.IWritableStream#write
         * @since 0.2.1
         */
        write: _gpfStreamSecureWrite(function (buffer) {
            var writer = this._writer; //eslint-disable-line no-invalid-this
            writer.write(buffer);
            writer.flush();
            return Promise.resolve();
        }),

        //endregion

        /**
         * @inheritdoc
         * @since 0.2.1
         */
        close: function () {
            this._writer.close();
            return this.$super();
        },

        /**
         * Stream writer
         *
         * @type {java.io.OutputStreamWriter}
         * @since 0.2.1
         */
        _writer: null

    });
<commit_msg>Removes @lends (#212)<commit_after>/**
 * @file Rhino specific stream implementation
 * @since 0.2.1
 */
/*#ifndef(UMD)*/
"use strict";
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfStreamSecureRead*/ // Generate a wrapper to secure multiple calls to stream#read
/*global _gpfStreamSecureWrite*/ // Generates a wrapper to secure multiple calls to stream#write
/*exported _GpfRhinoBaseStream*/ // gpf.rhino.BaseStream
/*exported _GpfRhinoReadableStream*/ // gpf.rhino.ReadableStream
/*exported _GpfRhinoWritableStream*/ // gpf.rhino.WritableStream
/*#endif*/

/*jshint rhino: true*/
/*eslint-env rhino*/

var
    _GpfRhinoBaseStream = _gpfDefine({
        $class: "gpf.rhino.BaseStream",

        /**
         * Base class wrapping Rhino streams
         *
         * @param {java.io.InputStream|java.io.OutputStream} stream Rhino input or output stream object
         *
         * @constructor gpf.rhino.BaseStream
         * @private
         * @since 0.2.1
         */
        constructor: function (stream) {
            this._stream = stream;
        },

        /**
         * Close the stream
         *
         * @return {Promise} Resolved when closed
         * @since 0.2.1
         */
        close: function () {
            this._stream.close();
            return Promise.resolve();
        },

        /**
         * Rhino stream object
         *
         * @type {java.io.InputStream|java.io.OutputStream}
         * @since 0.2.1
         */
        _stream: null

    }),

    /**
     * Wraps a readable stream from Rhino into a IReadableStream
     *
     * @param {java.io.InputStream} stream Rhino stream object
     *
     * @class gpf.rhino.ReadableStream
     * @extends gpf.rhino.BaseStream
     * @implements {gpf.interfaces.IReadableStream}
     * @since 0.2.1
     */
    _GpfRhinoReadableStream = _gpfDefine({
        $class: "gpf.rhino.ReadableStream",
        $extend: "gpf.rhino.BaseStream",

        //region gpf.interfaces.IReadableStream

        /**
         * Process error that occurred during the stream reading
         *
         * @param {Error} e Error coming from read
         * @return {Promise} Read result replacement
         * @since 0.2.1
         */
        _handleError: function (e) {
            if (e.message.indexOf("java.util.NoSuchElementException") === 0) {
                // Empty stream
                return Promise.resolve();
            }
            return Promise.reject(e);
        },

        /**
         * @gpf:sameas gpf.interfaces.IReadableStream#read
         * @since 0.2.1
         */
        read: _gpfStreamSecureRead(function (output) {
            try {
                var scanner = new java.util.Scanner(this._stream); //eslint-disable-line no-invalid-this
                return output.write(String(scanner.useDelimiter("\\A").next()));
            } catch (e) {
                return this._handleError(e); //eslint-disable-line no-invalid-this
            }
        })

        //endregion

    }),

    /**
     * Wraps a writable stream from Rhino into a IWritableStream
     *
     * @param {java.io.OutputStream} stream Rhino stream object
     *
     * @class gpf.rhino.WritableStream
     * @extends gpf.rhino.BaseStream
     * @implements {gpf.interfaces.IWritableStream}
     * @since 0.2.1
     */
    _GpfRhinoWritableStream = _gpfDefine({
        $class: "gpf.rhino.WritableStream",
        $extend: "gpf.rhino.BaseStream",

        constructor: function (stream) {
            this.$super(stream);
            this._writer = new java.io.OutputStreamWriter(stream);
        },

        //region gpf.interfaces.IWritableStream

        /**
         * @gpf:sameas gpf.interfaces.IWritableStream#write
         * @since 0.2.1
         */
        write: _gpfStreamSecureWrite(function (buffer) {
            var writer = this._writer; //eslint-disable-line no-invalid-this
            writer.write(buffer);
            writer.flush();
            return Promise.resolve();
        }),

        //endregion

        /**
         * @inheritdoc
         * @since 0.2.1
         */
        close: function () {
            this._writer.close();
            return this.$super();
        },

        /**
         * Stream writer
         *
         * @type {java.io.OutputStreamWriter}
         * @since 0.2.1
         */
        _writer: null

    });
<|endoftext|>


<commit_before>const fs = require('fs');
const exec = require('child_process').exec;
const moment = require('moment');

/*****************************************************************
    0.........1.........2.........3.........4.........5.........
0   ------------------------------------------------------------
1   ---##----##----####-------##------##---#####---#####--------
2   ---####--##---##--##------##-----------##------##-----------
3   ---##-##-##---##--##------##------##---####----####---------
4   ---##--####---##--##------##------##---##------##-----------
5   ---##----##----####-------#####---##---##------#####--------
6   ------------------------------------------------------------
// run in console to draw on github timeline:
a = document.getElementsByClassName('day')
for (let i=0, l=a.length; i<l; i++ ){
  a[i].setAttribute('fill', '#c6e48b')
  a[i].addEventListener('click', ()=>{ a[i].setAttribute('fill', '#196127') })
  a[i].addEventListener('contextmenu', ()=>{ a[i].setAttribute('fill', '#c6e48b') })
}
*****************************************************************/

let days = [
  '------------------------------------------------------------'.split(''),
  '---##--##--###----##-----##--##--##--##--#-#-#--------------'.split(''),
  '---###-##-##-##----#--#--#--####--#--#---#-#-#--------------'.split(''),
  '---######-##-##----##-#-##-##--##-####---#-#-#--------------'.split(''),
  '---##-###-##-##----######--######--##-----------------------'.split(''),
  '---##--##--###------##-##-###--###-##----#-#-#--------------'.split(''),
  '------------------------------------------------------------'.split('')
];

let offset = 13; // because the day i wrote this was 12 days after %60 == 0
// find indexes
let x = ( moment().diff(moment().startOf('year'), 'days') - offset ) % 60;
let y = moment().weekday() % 7;
// define if it s letter day or not
let isPixel = days[y][x] == '#';
log = (...opts) => {
  console.log( (isPixel?'#':'-')+' ['+moment().format('M-D-YY, h:mm a')+'] -', opts.join(' ') );
}
// Randomize:
// if it IS an update day, LOW exit likelyness
if ( isPixel && Math.random()<.2 ) {
  return log('Busy day but not now...');
}
// if it IS NOT an update day, HIGH exit likelyness
if ( !isPixel && Math.random()<.8 ) {
  return log('Not a busy day, not now...');
}

const emos = ["😀","😃","😄","😁","😆","😅","😂","😊","😇","🙂","🙃","😉","😌","😍","😘","😗","😙","😚",
  "😋","😜","😝","😛","🤑","🤗","🤓","😎","😏","😒","😞","😔","😟","😕","🙁","☹","😣","😖","😫","😩","😤",
  "😠","😡","😶","😐","😑","😯","😦","😧","😮","😲","😵","😳","😱","😨","😰","😢","😥","😭","😓","😪","😴",
  "🙄","🤔","😬","🤐","😷","🤒","🤕","😈","👿","👹","👺","💩","👻","💀","☠","👽","👾","🤖","🎃","😺","😸",
  "😹","😻","😼","😽","🙀","😿","😾","👐","🙌","👏","🙏","👍","👎","👊","✊","✌","🤘","👌","👈","👉","👆",
  "👇","☝","✋","🖐","🖖","👋","💪","🖕","✍","💅","🖖","💄","💋","👄","👅","👂","👃","👣","👁","👀","🗣",
  "👤","👥","👶","👦","👧","👨","👩","👱","👱","👴","👵","👲","👳","👳","👮","👮","👷","👷","💂","💂","🕵",
  "🕵","👩","👨","👩","🌾","👨","🌾","🍳","👨","🍳","👩","🎓","👨","👩","👨","🎤","👩","🏫","👨","🏫","👩",
  "🏭","👨","💻","👚","👕","👖","👔","👗","👙","👘","👠","👡","👢","👞","👟","👒","🎩","🎓","👑","⛑","🎒",
  "👝","👛","👜","💼","👓","🕶","🌂","☂"
];

// generate commit message
let n = 10;
let code = '';
let message = ''
while ( n-- > 0 )
  message += emos[Math.floor(Math.random()*emos.length)] + ' '
// generate random code
n = 3 + Math.random() * 10;
while ( n-- > 0 )
  code += emos[Math.floor(Math.random()*emos.length)] + ' '
  if ( Math.random() > .8 ) code += os.EOL;//' \r\n';
// save code
fs.writeFileSync('jam.txt', code, 'utf8');
// push changes to github
exec('git pull && git add jam.txt && git commit -m "'+message+'" && git push', (error, stdout, stderr)=>{
  if (error) {
    return log('Error:', error, error.code);
  }
  log('√ Pushed to Git -', message);
})

<commit_msg>Fix day index<commit_after>const fs = require('fs');
const exec = require('child_process').exec;
const moment = require('moment');

/*****************************************************************
    0.........1.........2.........3.........4.........5.........
0   ------------------------------------------------------------
1   ---##----##----####-------##------##---#####---#####--------
2   ---####--##---##--##------##-----------##------##-----------
3   ---##-##-##---##--##------##------##---####----####---------
4   ---##--####---##--##------##------##---##------##-----------
5   ---##----##----####-------#####---##---##------#####--------
6   ------------------------------------------------------------
// run in console to draw on github timeline:
a = document.getElementsByClassName('day')
for (let i=0, l=a.length; i<l; i++ ){
  a[i].setAttribute('fill', '#c6e48b')
  a[i].addEventListener('click', ()=>{ a[i].setAttribute('fill', '#196127') })
  a[i].addEventListener('contextmenu', ()=>{ a[i].setAttribute('fill', '#c6e48b') })
}
*****************************************************************/

let days = [
  '------------------------------------------------------------'.split(''),
  '---##--##--###----##-----##--##--##--##--#-#-#--------------'.split(''),
  '---###-##-##-##----#--#--#--####--#--#---#-#-#--------------'.split(''),
  '---######-##-##----##-#-##-##--##-####---#-#-#--------------'.split(''),
  '---##-###-##-##----######--######--##-----------------------'.split(''),
  '---##--##--###------##-##-###--###-##----#-#-#--------------'.split(''),
  '------------------------------------------------------------'.split('')
];

let offset = 18; // because the day i wrote this was 12 days after %60 == 0
// find indexes
let x = ( Math.floor((moment().diff(moment().startOf('year'), 'days') )/7-17) ) % 60;
let y = moment().weekday() % 7;
// define if it s letter day or not
let isPixel = days[y][x] == '#';
log = (...opts) => {
  console.log( (isPixel?'#':'-')+' ['+moment().format('M-D-YY, h:mm a')+'] -', opts.join(' ') );
}

// Randomize:
// if it IS an update day, LOW exit likelyness
if ( isPixel && Math.random()<.15 ) {
  return log('Busy day but not now...');
}
// if it IS NOT an update day, HIGH exit likelyness
if ( !isPixel && Math.random()<.8 ) {
  return log('Not a busy day, not now...');
}

const emos = ["😀","😃","😄","😁","😆","😅","😂","😊","😇","🙂","🙃","😉","😌","😍","😘","😗","😙","😚",
  "😋","😜","😝","😛","🤑","🤗","🤓","😎","😏","😒","😞","😔","😟","😕","🙁","☹","😣","😖","😫","😩","😤",
  "😠","😡","😶","😐","😑","😯","😦","😧","😮","😲","😵","😳","😱","😨","😰","😢","😥","😭","😓","😪","😴",
  "🙄","🤔","😬","🤐","😷","🤒","🤕","😈","👿","👹","👺","💩","👻","💀","☠","👽","👾","🤖","🎃","😺","😸",
  "😹","😻","😼","😽","🙀","😿","😾","👐","🙌","👏","🙏","👍","👎","👊","✊","✌","🤘","👌","👈","👉","👆",
  "👇","☝","✋","🖐","🖖","👋","💪","🖕","✍","💅","🖖","💄","💋","👄","👅","👂","👃","👣","👁","👀","🗣",
  "👤","👥","👶","👦","👧","👨","👩","👱","👱","👴","👵","👲","👳","👳","👮","👮","👷","👷","💂","💂","🕵",
  "🕵","👩","👨","👩","🌾","👨","🌾","🍳","👨","🍳","👩","🎓","👨","👩","👨","🎤","👩","🏫","👨","🏫","👩",
  "🏭","👨","💻","👚","👕","👖","👔","👗","👙","👘","👠","👡","👢","👞","👟","👒","🎩","🎓","👑","⛑","🎒",
  "👝","👛","👜","💼","👓","🕶","🌂","☂"
];

// generate commit message
let n = 10;
let code = '';
let message = ''
while ( n-- > 0 )
  message += emos[Math.floor(Math.random()*emos.length)] + ' '
// generate random code
n = 3 + Math.random() * 10;
while ( n-- > 0 )
  code += emos[Math.floor(Math.random()*emos.length)] + ' '
  if ( Math.random() > .8 ) code += os.EOL;//' \r\n';
// save code
fs.writeFileSync('jam.txt', code, 'utf8');
// push changes to github
exec('git pull && git add jam.txt && git commit -m "'+message+'" && git push', (error, stdout, stderr)=>{
  if (error) {
    return log('Error:', error, error.code);
  }
  log('√ Pushed to Git -', message);
})

<|endoftext|>


<commit_before>Template.cards.rendered = function() {
    var _this = this,
        cards = _this.$(".cards");

    if (Meteor.user().isBoardMember()) {
        cards.sortable({
            connectWith: ".js-sortable",
            tolerance: 'pointer',
            appendTo: 'body',
            helper: "clone",
            items: '.list-card:not(.placeholder, .hide, .js-composer)',
            placeholder: 'list-card placeholder',
            start: function (event, ui) {
                $('.list-card.placeholder').height(ui.item.height());
            },
            stop: function(event, ui) {
                var data = new Utils.getCardData(ui.item);
                Meteor.update(data.cardId, {
                    $set: {
                        listId: data.listId,
                        sort: data.sort
                    }
                });
            }
        }).disableSelection();

        Utils.liveEvent('mouseover', function($this) {
            $this.find('.js-member-droppable').droppable({
                hoverClass: "draggable-hover-card",
                accept: '.js-member',
                drop: function(event, ui) {
                    var memberId = Blaze.getData(ui.draggable.get(0)).userId;
                    var cardId = Blaze.getData(this)._id;
                    Cards.update(cardId, {$addToSet: { members: memberId}});
                }
            });
        });
    }

    // update height add, update, remove resize board height.
    Cards.find().observe({
        added: Utils.resizeHeight('.board-canvas'),
        updated: Utils.resizeHeight('.board-canvas'),
        removed: Utils.resizeHeight('.board-canvas')
    });
};

Template.formLabel.rendered = function() {
    this.find('.js-autofocus').focus();
};

Template.cardMorePopup.rendered = function() {
    this.find('.js-autoselect').select();
};
<commit_msg>Fix #79<commit_after>Template.cards.rendered = function() {
    var _this = this,
        cards = _this.$(".cards");

    if (Meteor.user().isBoardMember()) {
        cards.sortable({
            connectWith: ".js-sortable",
            tolerance: 'pointer',
            appendTo: 'body',
            helper: "clone",
            items: '.list-card:not(.placeholder, .hide, .js-composer)',
            placeholder: 'list-card placeholder',
            start: function (event, ui) {
                $('.list-card.placeholder').height(ui.item.height());
            },
            stop: function(event, ui) {
                var data = new Utils.getCardData(ui.item);
                Cards.update(data.cardId, {
                    $set: {
                        listId: data.listId,
                        sort: data.sort
                    }
                });
            }
        }).disableSelection();

        Utils.liveEvent('mouseover', function($this) {
            $this.find('.js-member-droppable').droppable({
                hoverClass: "draggable-hover-card",
                accept: '.js-member',
                drop: function(event, ui) {
                    var memberId = Blaze.getData(ui.draggable.get(0)).userId;
                    var cardId = Blaze.getData(this)._id;
                    Cards.update(cardId, {$addToSet: { members: memberId}});
                }
            });
        });
    }

    // update height add, update, remove resize board height.
    Cards.find().observe({
        added: Utils.resizeHeight('.board-canvas'),
        updated: Utils.resizeHeight('.board-canvas'),
        removed: Utils.resizeHeight('.board-canvas')
    });
};

Template.formLabel.rendered = function() {
    this.find('.js-autofocus').focus();
};

Template.cardMorePopup.rendered = function() {
    this.find('.js-autoselect').select();
};
<|endoftext|>