<commit_before>var placeholder = "Search, drag and drop video, or paste its URL...";

var removeImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/x-4x.png";
var pauseImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/media-pause-4x.png";
var playImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/media-play-4x.png";

var videoUrl;
var videoName;
var videoTime = null;

var videos = [];
var videoCounter = -1;
var videoIteration = -1;
var videoPaused;
var timer;

function Timer(callback, delay) {
  var timerId, start, remaining = delay;

  this.pause = function() {
      window.clearTimeout(timerId);
      remaining -= new Date() - start;
  };

  this.resume = function() {
      start = new Date();
      window.clearTimeout(timerId);
      timerId = window.setTimeout(callback, remaining);
  };

  this.resume();
}

function msConversion(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}

function highlight(i) {
  i++;
  $("tr:nth-child(" + i + ")").attr("id", "newSelected");
  $("tr.selected").removeClass("selected");
  $("#newSelected").addClass("selected");
  $("#newSelected").removeAttr("id");
}

function addVideoToList(name, time) {
  $("#videosTable").append("
" + name + "<button class=\"tableButton\" onclick=\"removeVideo(this);\"></button>	" + time + "
");
}

function playVideo() {
  highlight(videoIteration);
  document.title = "Streamly - " + videos[videoIteration]["name"];

  var embedUrl = videos[videoIteration]["url"].replace("/watch?v=", "/embed/") + "?autoplay=1";
  $("#youtube").attr("src", embedUrl);
  $("#pauseImg").attr("src", pauseImgSrc);
}

function loopVideo() {
  videoIteration++;
  playVideo();
  timer = new Timer(function() {
    if (videoIteration < videoCounter) {
      loopVideo();
    }
    else {
      timer.pause();
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
    }
  }, videos[videoIteration]["time"] + 2000);
}

function pauseVideo() {
  if (!videoPaused) {
    timer.pause();
    $("#pauseImg").attr("src", playImgSrc);
    videoPaused = true;
  }
  else {
    timer.resume();
    $("#pauseImg").attr("src", pauseImgSrc);
    videoPaused = false;
  }
}

function backVideo() {
  if (videoIteration - 2 > -2) {
    videoIteration = videoIteration - 2;
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;
    loopVideo();
  }
}

function forwardVideo() {
  if (videoIteration + 1 <= videoCounter) {
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;
    loopVideo();
  }
}

function setPlaylist() {
  if (videos.length > 0) {
    var playlist = JSON.stringify(videos);
    playlist = encodeURIComponent(playlist);
    playlist = window.btoa(playlist);
    playlist = encodeURIComponent(playlist);
    window.location.hash = playlist;
  }
  else {
    window.location.hash = "";
  }
}

function getPlaylist() {
  if (window.location.hash.substr(1) !== "") {
    var playlist = window.location.hash.substr(1);
    playlist = decodeURIComponent(playlist);
    playlist = window.atob(playlist);
    playlist = decodeURIComponent(playlist);
    playlist = JSON.parse(playlist);
    videos = playlist;

    for (i = 0; i < videos.length; i++) {
      videoCounter = i;
      var printTime = msConversion(videos[videoCounter]["time"]);
      addVideoToList(videos[videoCounter]["name"], printTime);
    }
    loopVideo();
  }
}

function getVideoData() {
  $.ajax({
    url: videoUrl,
    type: 'GET',
    success: function(res) {
      var data = $(res.responseText);
      try {
        videoName = data.find("span#eow-title");
        videoName = videoName[0].textContent;
        videoName = videoName.trim();
      } catch(err) {
        videoName = prompt("Please enter the name of the video", "");
      }
      try {
        videoTime = null;
        for (iteration in data) {
          var str = data[iteration].innerHTML;
          if (videoTime == null && typeof str != "undefined") {
            videoTime = str.match(/,"length_seconds":"\d+",/g);
          }
        }
        videoTime = videoTime[0];
        videoTime = videoTime.replace(/,"length_seconds":"/g, "").replace(/",/g, "");
        videoTime = +videoTime * 1000;
      } catch(err) {
        videoTime = prompt("Please enter the length of the video", "3:00");
        videoTime = videoTime.split(":");
        videoTime = (+videoTime[0]) * 60 + (+videoTime[1]);
        videoTime = videoTime * 1000;
      }
    }
  });
}

function addVideo() {
  videoCounter++;
  var video = {};
  video["name"] = videoName;
  video["time"] = videoTime;
  video["url"] = videoUrl;
  videos[videoCounter] = video;

  var printTime = msConversion(videos[videoCounter]["time"]);

  addVideoToList(videoName, printTime);

  setPlaylist();

  if (videoCounter == 0 || timer == 0) {
    loopVideo();
  }
}

function removeVideo(element) {
  var index = $(".tableButton").index(element);
  if (index == videoIteration) {
    if (videoIteration + 1 <= videoCounter) {
      forwardVideo();
      videoIteration--;
    }
    else {
      if (timer != 0) {
        timer.pause();
      }
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
      videoIteration--;
    }
  }
  else if (index < videoIteration) {
    videoIteration--;
  }
  videoCounter--;
  videos.splice(index, 1);
  index++;
  $("tr:nth-child(" + index + ")").remove();
  setPlaylist();
}

function input(kind) {
  var input = $("#inputBox").val();
  if (input != "") {
    switch (kind) {
      case 0:
        window.open("https://www.youtube.com/results?search_query=" + input.replace(/ /g, "+"));
        $("#inputBox").val("").attr("placeholder", placeholder);
        break;
      case 1:
        videoUrl = input.trim();
        $("#inputBox").val("").attr("placeholder", "Loading video data from YouTube...");
        getVideoData();
        break;
    }
  }
}

$(document).ajaxStop(function() {
  $("#inputBox").val("").attr("placeholder", placeholder);
  addVideo();
});

function onDrop(event) {
  var data = event.dataTransfer.getData("URL");
  event.target.textContent = data;
  $("#inputBox").val(data);
  input(1);
  event.preventDefault();
}
<commit_msg>changed to `type` for clarity<commit_after>var placeholder = "Search, drag and drop video, or paste its URL...";

var removeImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/x-4x.png";
var pauseImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/media-pause-4x.png";
var playImgSrc = "//cdn.rawgit.com/iconic/open-iconic/master/png/media-play-4x.png";

var videoUrl;
var videoName;
var videoTime = null;

var videos = [];
var videoCounter = -1;
var videoIteration = -1;
var videoPaused;
var timer;

function Timer(callback, delay) {
  var timerId, start, remaining = delay;

  this.pause = function() {
      window.clearTimeout(timerId);
      remaining -= new Date() - start;
  };

  this.resume = function() {
      start = new Date();
      window.clearTimeout(timerId);
      timerId = window.setTimeout(callback, remaining);
  };

  this.resume();
}

function msConversion(millis) {
  var minutes = Math.floor(millis / 60000);
  var seconds = ((millis % 60000) / 1000).toFixed(0);
  return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}

function highlight(i) {
  i++;
  $("tr:nth-child(" + i + ")").attr("id", "newSelected");
  $("tr.selected").removeClass("selected");
  $("#newSelected").addClass("selected");
  $("#newSelected").removeAttr("id");
}

function addVideoToList(name, time) {
  $("#videosTable").append("
" + name + "<button class=\"tableButton\" onclick=\"removeVideo(this);\"></button>	" + time + "
");
}

function playVideo() {
  highlight(videoIteration);
  document.title = "Streamly - " + videos[videoIteration]["name"];

  var embedUrl = videos[videoIteration]["url"].replace("/watch?v=", "/embed/") + "?autoplay=1";
  $("#youtube").attr("src", embedUrl);
  $("#pauseImg").attr("src", pauseImgSrc);
}

function loopVideo() {
  videoIteration++;
  playVideo();
  timer = new Timer(function() {
    if (videoIteration < videoCounter) {
      loopVideo();
    }
    else {
      timer.pause();
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
    }
  }, videos[videoIteration]["time"] + 2000);
}

function pauseVideo() {
  if (!videoPaused) {
    timer.pause();
    $("#pauseImg").attr("src", playImgSrc);
    videoPaused = true;
  }
  else {
    timer.resume();
    $("#pauseImg").attr("src", pauseImgSrc);
    videoPaused = false;
  }
}

function backVideo() {
  if (videoIteration - 2 > -2) {
    videoIteration = videoIteration - 2;
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;
    loopVideo();
  }
}

function forwardVideo() {
  if (videoIteration + 1 <= videoCounter) {
    if (timer != 0) {
      timer.pause();
    }
    timer = 0;
    loopVideo();
  }
}

function setPlaylist() {
  if (videos.length > 0) {
    var playlist = JSON.stringify(videos);
    playlist = encodeURIComponent(playlist);
    playlist = window.btoa(playlist);
    playlist = encodeURIComponent(playlist);
    window.location.hash = playlist;
  }
  else {
    window.location.hash = "";
  }
}

function getPlaylist() {
  if (window.location.hash.substr(1) !== "") {
    var playlist = window.location.hash.substr(1);
    playlist = decodeURIComponent(playlist);
    playlist = window.atob(playlist);
    playlist = decodeURIComponent(playlist);
    playlist = JSON.parse(playlist);
    videos = playlist;

    for (i = 0; i < videos.length; i++) {
      videoCounter = i;
      var printTime = msConversion(videos[videoCounter]["time"]);
      addVideoToList(videos[videoCounter]["name"], printTime);
    }
    loopVideo();
  }
}

function getVideoData() {
  $.ajax({
    url: videoUrl,
    type: 'GET',
    success: function(res) {
      var data = $(res.responseText);
      try {
        videoName = data.find("span#eow-title");
        videoName = videoName[0].textContent;
        videoName = videoName.trim();
      } catch(err) {
        videoName = prompt("Please enter the name of the video", "");
      }
      try {
        videoTime = null;
        for (iteration in data) {
          var str = data[iteration].innerHTML;
          if (videoTime == null && typeof str != "undefined") {
            videoTime = str.match(/,"length_seconds":"\d+",/g);
          }
        }
        videoTime = videoTime[0];
        videoTime = videoTime.replace(/,"length_seconds":"/g, "").replace(/",/g, "");
        videoTime = +videoTime * 1000;
      } catch(err) {
        videoTime = prompt("Please enter the length of the video", "3:00");
        videoTime = videoTime.split(":");
        videoTime = (+videoTime[0]) * 60 + (+videoTime[1]);
        videoTime = videoTime * 1000;
      }
    }
  });
}

function addVideo() {
  videoCounter++;
  var video = {};
  video["name"] = videoName;
  video["time"] = videoTime;
  video["url"] = videoUrl;
  videos[videoCounter] = video;

  var printTime = msConversion(videos[videoCounter]["time"]);

  addVideoToList(videoName, printTime);

  setPlaylist();

  if (videoCounter == 0 || timer == 0) {
    loopVideo();
  }
}

function removeVideo(element) {
  var index = $(".tableButton").index(element);
  if (index == videoIteration) {
    if (videoIteration + 1 <= videoCounter) {
      forwardVideo();
      videoIteration--;
    }
    else {
      if (timer != 0) {
        timer.pause();
      }
      timer = 0;
      $("#youtube").attr("src", "");
      document.title = "Streamly";
      videoIteration--;
    }
  }
  else if (index < videoIteration) {
    videoIteration--;
  }
  videoCounter--;
  videos.splice(index, 1);
  index++;
  $("tr:nth-child(" + index + ")").remove();
  setPlaylist();
}

function input(type) {
  var input = $("#inputBox").val();
  if (input != "") {
    switch (type) {
      case 0:
        window.open("https://www.youtube.com/results?search_query=" + input.replace(/ /g, "+"));
        $("#inputBox").val("").attr("placeholder", placeholder);
        break;
      case 1:
        videoUrl = input.trim();
        $("#inputBox").val("").attr("placeholder", "Loading video data from YouTube...");
        getVideoData();
        break;
    }
  }
}

$(document).ajaxStop(function() {
  $("#inputBox").val("").attr("placeholder", placeholder);
  addVideo();
});

function onDrop(event) {
  var data = event.dataTransfer.getData("URL");
  event.target.textContent = data;
  $("#inputBox").val(data);
  input(1);
  event.preventDefault();
}
<|endoftext|>


<commit_before>var config = require('./config.json')
var Slack = require('slack-node');
var vCard = require('vcards-js');
var request = require('request');
var fs = require('fs');

slack = new Slack(config.slackToken);
vCard = vCard();

console.log(config);

var download = function(uri, filename, callback){
  request.head(uri, function(err, res, body){
    request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
  });
};

slack.api("users.list", function(err, response) {
	response.members.forEach(function(user) {

		download(user.profile.image_72,  user.name+'.jpg' , function () {

		//set properties
		vCard.firstName = user.profile.first_name;
		vCard.lastName = user.profile.last_name;
		vCard.organization = config.organization;
		vCard.photo.embedFromFile(user.name+'.jpg');

		vCard.cellPhone = user.profile.phone;
		vCard.title = user.profile.title;
		vCard.email = user.profile.email;

		vCard.socialUrls['skype'] = user.profile.skype;

		//save to file
		vCard.saveToFile('./contacts/'+user.name+'.vcf');

		//Clean photo after save
		fs.unlink(user.name+'.jpg');
		});
	});
});

<commit_msg>Removed image download<commit_after>var config = require('./config.json')
var Slack = require('slack-node');
var vCard = require('vcards-js');
var fs = require('fs');

slack = new Slack(config.slackToken);
vCard = vCard();

slack.api("users.list", function(err, response) {
	response.members.forEach(function(user) {

	//set properties
	vCard.firstName = user.profile.first_name;
	vCard.lastName = user.profile.last_name;
	vCard.organization = config.organization;
	vCard.photo.attachFromUrl(user.profile.image_72, 'JPEG');

	vCard.cellPhone = user.profile.phone;
	vCard.title = user.profile.title;
	vCard.email = user.profile.email;

	vCard.socialUrls['skype'] = user.profile.skype;

	//save to file
	vCard.saveToFile('./contacts/'+user.name+'.vcf');
	});
});

<|endoftext|>


<commit_before>'use strict';

var express = require('express');

var app = express();

app.use('/components/gh-issues', express.static( __dirname));
app.use('/components', express.static(__dirname + '/bower_components'));

app.get('/hello', function (req, res) {
  res.status(200).send('Hello, world!');
});

var server = app.listen(process.env.PORT || '8080', function () {
  console.log('App listening on port %s', server.address().port);
});
<commit_msg>auto redirect to example page<commit_after>'use strict';

var express = require('express');

var app = express();

app.use('/components/gh-issues', express.static( __dirname));
app.use('/components', express.static(__dirname + '/bower_components'));

app.get('/', function(req, res){
  res.redirect('/components/gh-issues/');
});

app.get('/hello', function (req, res) {
  res.status(200).send('Hello, world!');
});

var server = app.listen(process.env.PORT || '8080', function () {
  console.log('App listening on port %s', server.address().port);
});
<|endoftext|>


<commit_before>var Botkit = require('botkit');
var BeepBoopBotkit = require('beepboop-botkit');
var StringArgv = require('string-argv');

var PORT = process.env.PORT
if (!PORT) {
    console.error('PORT is required');
    process.exit(1);
}

var VERIFY_TOKEN = process.env.SLACK_VERIFY_TOKEN
if (!VERIFY_TOKEN) {
  console.error('SLACK_VERIFY_TOKEN is required')
  process.exit(1)
}

var controller = Botkit.slackbot({
  // reconnect to Slack RTM when connection goes bad
  retry: Infinity,
  send_via_rtm: true,
  debug: false
});

console.log('Starting in Beep Boop multi-team mode')
var BeepBoop = BeepBoopBotkit.start(controller, { debug: true, scopes: ['channels:history'] })
var MarkovChain = require('markovchain');
var JSMegaHal = require('jsmegahal');

var COMMAND_MAPPINGS = {
    "/incaseofjoshrant": handle_incaseofjoshrant,
    "/markov": handle_markov,
    "/megahal": handle_megahal,
    "/echo": handle_echo
};

controller.setupWebserver(PORT, function(err, webserver) {
    if (err) {
        console.error(err)
        process.exit(1)
    }
    // Setup our slash command webhook endpoints
    controller.createWebhookEndpoints(webserver)
});

controller.on('slash_command', function(bot, message) {
    if (message.token !== VERIFY_TOKEN) {
        return bot.res.send(401, 'Unauthorized');
    }
    if (!COMMAND_MAPPINGS[message.command]) {
        bot.replyAcknowledge();
        return;
    }

    var params = StringArgv(message.text);

    COMMAND_MAPPINGS[message.command](bot, message, params);
});

// receive an interactive message, and reply with a message that will replace the original
controller.on('interactive_message_callback', function(bot, message) {
    if (message.token !== VERIFY_TOKEN) {
        return bot.res.send(401, 'Unauthorized');
    }

    return bot.res.send(200, ''); //do nothing
});

// ============ various slash command handlers =============

function handle_incaseofjoshrant(bot, message, params) {
    bot.replyPublicDelayed(message, {
        "response_type": "in_channel",
        "attachments": [{
            "title": '@' + message.user_name + ' activated emergency alert procedure',
            "image_url": "http://i.imgur.com/wtYhyuN.png"
        }]
    }, function() {
        return bot.res.send(200, '');
    });
}

function handle_markov(bot, message, params) {
    //Hack in and get our access token
    var workerKey = Object.keys(BeepBoop.workers)[0];
    var token = BeepBoop.workers[workerKey].resource.SlackAccessToken;

    var count = 500;
    if (params && params.length > 0) {
        count = Number(params[0]);
    }

    //Get our message history
    bot.api.channels.history({
        channel: message.channel_id,
        token: token,
        count: count
    }, function(err, data) {

        var m = new MarkovChain('');
        for (var i = 0; i < data.messages.length; i++) {
            if (data.messages[i].user) {
                m.parse(data.messages[i].text);
            }
        }

        var title = "@" + message.user_name + " requested a markov chain based on the last " + count + " messages";

        var text = m.process();
        bot.replyPublicDelayed(message, {
            "response_type": "in_channel",
            "attachments": [{
                 "title": title,
                "text": text
            }]
        }, function() {
            return bot.res.send(200, '');
        });
    });
}

function handle_megahal(bot, message, params) {
    //Hack in and get our access token
    var workerKey = Object.keys(BeepBoop.workers)[0];
    var token = BeepBoop.workers[workerKey].resource.SlackAccessToken;

    var count = 500;
    var order = 3;
    var question = undefined;
    if (params && params.length > 0) {
        question = params.join(' ');
    }

    //Get our message history
    bot.api.channels.history({
        channel: message.channel_id,
        token: token,
        count: count
    }, function(err, data) {

        var m = new JSMegaHal(order);
        var currentUser = null;
        var currentMessage = null;
        for (var i = 0; i < data.messages.length; i++) {
            var msg = data.messages[i];

            if (!msg.user) {
                continue;
            }

            if (msg.user !== currentUser) {
                if (currentMessage) {
                    console.log("Adding: " + currentMessage);
                    m.add(currentMessage);
                }
                currentUser = msg.user;
                currentMessage = msg.text;
            } else {
                //Same user with multiple messages should be combined
                currentMessage += '. ' + msg.text;
            }
        }

        console.log("Adding: " + currentMessage);
        m.add(currentMessage);

        var title = null;
        if (question) {
            title = "@" + message.user_name + " requested a megahal response to: '" + question + "'";
        } else {
            title = "@" + message.user_name + " requested a random megahal response";
        }

        var text = m.getReply(question);
        bot.replyPublicDelayed(message, {
            "response_type": "in_channel",
            "attachments": [{
                 "title": title,
                "text": text
            }]
        }, function() {
            return bot.res.send(200, '');
        });
    });
}

function handle_echo(bot, message, params) {
    var text = 'Whatever...'
    if (params) {
        var obj = null;
        switch (params[0]) {
            case "beepboop":
                obj = BeepBoop;
                break;
            case "beepboopbotkit":
                obj = BeepBoopBotkit;
                break;
            case "controller":
                obj = controller;
                break;
            case "message":
                obj = message;
                break;
            default:
                obj = bot;
                break;
        }
        for (var i = 1; i < params.length; i++) {
            obj = obj[params[i]];
            if (obj === null || obj === undefined) {
                text = "Couldnt find " + params[i] + " in " + obj;
                break;
            }
        }

        if (obj == null || obj == undefined) {
            text = 'null/undefined';
        } else if (obj instanceof String) {
            text = obj + ':(String)';
        } else if (obj instanceof Number) {
            text = obj + ':(Number)';
        } else if (obj instanceof Object) {
            text = obj + ':(Object) has keys ' + Object.keys(obj);
        } else {
            text = obj + ':(' + typeof obj + ') has keys ' + Object.keys(obj);
        }
    }
    bot.replyPublicDelayed(message, {
        "response_type": "in_channel",
        "attachments": [{
            "title": '/echo ' + params.join(' '),
            "text": text
        }]
    }, function() {
        return bot.res.send(200, '');
    });
}

<commit_msg>disorder 2<commit_after>var Botkit = require('botkit');
var BeepBoopBotkit = require('beepboop-botkit');
var StringArgv = require('string-argv');

var PORT = process.env.PORT
if (!PORT) {
    console.error('PORT is required');
    process.exit(1);
}

var VERIFY_TOKEN = process.env.SLACK_VERIFY_TOKEN
if (!VERIFY_TOKEN) {
  console.error('SLACK_VERIFY_TOKEN is required')
  process.exit(1)
}

var controller = Botkit.slackbot({
  // reconnect to Slack RTM when connection goes bad
  retry: Infinity,
  send_via_rtm: true,
  debug: false
});

console.log('Starting in Beep Boop multi-team mode')
var BeepBoop = BeepBoopBotkit.start(controller, { debug: true, scopes: ['channels:history'] })
var MarkovChain = require('markovchain');
var JSMegaHal = require('jsmegahal');

var COMMAND_MAPPINGS = {
    "/incaseofjoshrant": handle_incaseofjoshrant,
    "/markov": handle_markov,
    "/megahal": handle_megahal,
    "/echo": handle_echo
};

controller.setupWebserver(PORT, function(err, webserver) {
    if (err) {
        console.error(err)
        process.exit(1)
    }
    // Setup our slash command webhook endpoints
    controller.createWebhookEndpoints(webserver)
});

controller.on('slash_command', function(bot, message) {
    if (message.token !== VERIFY_TOKEN) {
        return bot.res.send(401, 'Unauthorized');
    }
    if (!COMMAND_MAPPINGS[message.command]) {
        bot.replyAcknowledge();
        return;
    }

    var params = StringArgv(message.text);

    COMMAND_MAPPINGS[message.command](bot, message, params);
});

// receive an interactive message, and reply with a message that will replace the original
controller.on('interactive_message_callback', function(bot, message) {
    if (message.token !== VERIFY_TOKEN) {
        return bot.res.send(401, 'Unauthorized');
    }

    return bot.res.send(200, ''); //do nothing
});

// ============ various slash command handlers =============

function handle_incaseofjoshrant(bot, message, params) {
    bot.replyPublicDelayed(message, {
        "response_type": "in_channel",
        "attachments": [{
            "title": '@' + message.user_name + ' activated emergency alert procedure',
            "image_url": "http://i.imgur.com/wtYhyuN.png"
        }]
    }, function() {
        return bot.res.send(200, '');
    });
}

function handle_markov(bot, message, params) {
    //Hack in and get our access token
    var workerKey = Object.keys(BeepBoop.workers)[0];
    var token = BeepBoop.workers[workerKey].resource.SlackAccessToken;

    var count = 500;
    if (params && params.length > 0) {
        count = Number(params[0]);
    }

    //Get our message history
    bot.api.channels.history({
        channel: message.channel_id,
        token: token,
        count: count
    }, function(err, data) {

        var m = new MarkovChain('');
        for (var i = 0; i < data.messages.length; i++) {
            if (data.messages[i].user) {
                m.parse(data.messages[i].text);
            }
        }

        var title = "@" + message.user_name + " requested a markov chain based on the last " + count + " messages";

        var text = m.process();
        bot.replyPublicDelayed(message, {
            "response_type": "in_channel",
            "attachments": [{
                 "title": title,
                "text": text
            }]
        }, function() {
            return bot.res.send(200, '');
        });
    });
}

function handle_megahal(bot, message, params) {
    //Hack in and get our access token
    var workerKey = Object.keys(BeepBoop.workers)[0];
    var token = BeepBoop.workers[workerKey].resource.SlackAccessToken;

    var count = 500;
    var order = 2;
    var question = undefined;
    if (params && params.length > 0) {
        question = params.join(' ');
    }

    //Get our message history
    bot.api.channels.history({
        channel: message.channel_id,
        token: token,
        count: count
    }, function(err, data) {

        var m = new JSMegaHal(order);
        var currentUser = null;
        var currentMessage = null;
        for (var i = 0; i < data.messages.length; i++) {
            var msg = data.messages[i];

            if (!msg.user) {
                continue;
            }

            if (msg.user !== currentUser) {
                if (currentMessage) {
                    console.log("Adding: " + currentMessage);
                    m.add(currentMessage);
                }
                currentUser = msg.user;
                currentMessage = msg.text;
            } else {
                //Same user with multiple messages should be combined
                currentMessage += '. ' + msg.text;
            }
        }

        console.log("Adding: " + currentMessage);
        m.add(currentMessage);

        var title = null;
        if (question) {
            title = "@" + message.user_name + " requested a megahal response to: '" + question + "'";
        } else {
            title = "@" + message.user_name + " requested a random megahal response";
        }

        var text = m.getReply(question);
        bot.replyPublicDelayed(message, {
            "response_type": "in_channel",
            "attachments": [{
                 "title": title,
                "text": text
            }]
        }, function() {
            return bot.res.send(200, '');
        });
    });
}

function handle_echo(bot, message, params) {
    var text = 'Whatever...'
    if (params) {
        var obj = null;
        switch (params[0]) {
            case "beepboop":
                obj = BeepBoop;
                break;
            case "beepboopbotkit":
                obj = BeepBoopBotkit;
                break;
            case "controller":
                obj = controller;
                break;
            case "message":
                obj = message;
                break;
            default:
                obj = bot;
                break;
        }
        for (var i = 1; i < params.length; i++) {
            obj = obj[params[i]];
            if (obj === null || obj === undefined) {
                text = "Couldnt find " + params[i] + " in " + obj;
                break;
            }
        }

        if (obj == null || obj == undefined) {
            text = 'null/undefined';
        } else if (obj instanceof String) {
            text = obj + ':(String)';
        } else if (obj instanceof Number) {
            text = obj + ':(Number)';
        } else if (obj instanceof Object) {
            text = obj + ':(Object) has keys ' + Object.keys(obj);
        } else {
            text = obj + ':(' + typeof obj + ') has keys ' + Object.keys(obj);
        }
    }
    bot.replyPublicDelayed(message, {
        "response_type": "in_channel",
        "attachments": [{
            "title": '/echo ' + params.join(' '),
            "text": text
        }]
    }, function() {
        return bot.res.send(200, '');
    });
}

<|endoftext|>


<commit_before>"use strict";

let verymodel = require('verymodel');
let lodash = require('lodash');
let assert = require('assert');
let pg = require('pg');
let async = require('async');
let Joi = require('joi');

let default_connection;

function positionBindings(sql) {
  var questionCount = 0;
  return sql.replace(/\?/g, function () {
    questionCount++;
    return '$' + questionCount;
  });
}

function Model() {
  verymodel.VeryModel.apply(this, arguments);
  if (!this.options.connection) this.options.connection = default_connection;

  this.getDB = function (callback) {
    pg.connect(this.options.connection, function (err, db, done) {
      callback(err, db, done);
    });
  };

  this.extendModel({
    getDB: function (callback) {
      pg.connect(model.options.connection, function (err, db, done) {
        callback(err, db, done);
      });
    }
  });
}

Model.prototype = Object.create(verymodel.VeryModel.prototype);

(function () {

  this.fromSQL = function (ropts) {
    assert.equal(typeof ropts, 'object');
    assert.equal(typeof ropts.name, 'string');
    assert.equal(typeof ropts.sql, 'function');

    if (ropts.instance) {
      return this.registerInstanceSQL(ropts);
    }
    return this.registerFactorySQL(ropts);
  }

  this.runQuery = function (opts, queries, callback) {
    return new Promise((resolve, reject) => {
      if (opts.validationError) {
        if (callback) {
          callback(opts.validationError);
        }
        return reject(opts.validationError);
      }
      this.getDB((err, client, dbDone) => {
        if (err) {
          dbDone();
          if (callback) callback(err);
          return reject(err);
        }
        async.reduce(queries, [], (rows, query, nextCB) => {
          client.query(query, (err, results) => {
            if (err) {
              return nextCB(err);
            }
            results.rows.forEach((row) => {
               rows.push(opts.model.create(row));
            });
            nextCB(undefined, rows);
          });
        }, (err, rows) => {
          if (!err) {
            if (rows.length === 0 && (opts.required || opts.oneResult)) {
              rows = null;
            } else if (opts.oneResult === true && rows.length > 0) {
                rows = rows[0];
            }
          }
          dbDone();
          if (callback) callback(err, rows);
          return err ? reject(err) : resolve(rows);
        });
      });
    });
  };

  function prepArgs(args, callback, opts) {
    callback = typeof args === 'function' ? args : callback;
    args = typeof args === 'object' ? args : {};
    args = lodash.defaults(args, opts.defaults || {});
    opts.validateOpts = opts.validateOpts || null;
    if (opts.validate) {
      let valRes = Joi.validate(args, opts.validate, opts.validateOpts);
      if (valRes.error) {
        opts.validationError = valRes.error;
      } else {
        args = valRes.value;
      }
    }
    return {callback, args};
  }

  function prepQuery(func, args, inst, model, name) {
    let queries = func.call(args, args, inst, model);

    if (!Array.isArray(queries)) {
      queries = [queries];
    }

    queries = queries.map((query) => {

      //if knex query builder
      if (typeof query === 'object' && query.constructor.name === 'QueryBuilder') {
        let knexQuery = query.toSQL();
        query = {
          text: positionBindings(knexQuery.sql),
          values: knexQuery.bindings
        };
      }
      if (typeof query === 'string') {
        query = {text: query};
      }
      return query;
    });
    return queries;
  }

  this.prepOpts = function (opts) {
    if (!opts.model) {
      opts.model = this;
    } else if (typeof opts.model === 'string') {
      opts.model = model_cache[opts.model];
    }
    return opts;
  };

  this.registerFactorySQL = function (opts) {
    if (typeof this[opts.name] !== 'undefined') {
      throw new Error(`Gatepost Model "${this.options.name}" already has a property named "${opts.name}"`);
    }
    opts = this.prepOpts(opts);
    this[opts.name] = (args, callback) => {
      let config = prepArgs(args, callback, opts, this);
      let query = prepQuery(opts.sql, config.args, null, this, opts.name);
      return this.runQuery(opts, query, config.callback);
    };
  };

  this.registerInstanceSQL = function (opts) {
    if (typeof this.controllers[opts.name] !== 'undefined') {
      throw new Error(`Instances of Gatepost Model "${this.options.name}" already have a property named "${opts.name}"`);
    }
    let extension = {};
    opts = this.prepOpts(opts);
    extension[opts.name] = function (args, callback) {
      let config = prepArgs(args, callback, opts);
      let errors = this.doValidate();
      if (errors.error !== null) {
        opts.validationError = errors;
      }
      let query = prepQuery(opts.sql, config.args, this, this.__verymeta.model, `inst-${opts.name}`);
      return this.__verymeta.model.runQuery(opts, query, config.callback);
    };
    this.extendModel(extension);
  };

}).call(Model.prototype);

module.exports = {
  setConnection: function (connection) {
    default_connection = connection;
  },
  Model: Model,
  getClient: function (callback) {
    pg.connect(default_connection, callback);
  }
}
<commit_msg>bugfix where error was validation object rather than validation.error<commit_after>"use strict";

let verymodel = require('verymodel');
let lodash = require('lodash');
let assert = require('assert');
let pg = require('pg');
let async = require('async');
let Joi = require('joi');

let default_connection;

function positionBindings(sql) {
  var questionCount = 0;
  return sql.replace(/\?/g, function () {
    questionCount++;
    return '$' + questionCount;
  });
}

function Model() {
  verymodel.VeryModel.apply(this, arguments);
  if (!this.options.connection) this.options.connection = default_connection;

  this.getDB = function (callback) {
    pg.connect(this.options.connection, function (err, db, done) {
      callback(err, db, done);
    });
  };

  this.extendModel({
    getDB: function (callback) {
      pg.connect(model.options.connection, function (err, db, done) {
        callback(err, db, done);
      });
    }
  });
}

Model.prototype = Object.create(verymodel.VeryModel.prototype);

(function () {

  this.fromSQL = function (ropts) {
    assert.equal(typeof ropts, 'object');
    assert.equal(typeof ropts.name, 'string');
    assert.equal(typeof ropts.sql, 'function');

    if (ropts.instance) {
      return this.registerInstanceSQL(ropts);
    }
    return this.registerFactorySQL(ropts);
  }

  this.runQuery = function (opts, queries, callback) {
    return new Promise((resolve, reject) => {
      if (opts.validationError) {
        if (callback) {
          callback(opts.validationError);
        }
        return reject(opts.validationError);
      }
      this.getDB((err, client, dbDone) => {
        if (err) {
          dbDone();
          if (callback) callback(err);
          return reject(err);
        }
        async.reduce(queries, [], (rows, query, nextCB) => {
          client.query(query, (err, results) => {
            if (err) {
              return nextCB(err);
            }
            results.rows.forEach((row) => {
               rows.push(opts.model.create(row));
            });
            nextCB(undefined, rows);
          });
        }, (err, rows) => {
          if (!err) {
            if (rows.length === 0 && (opts.required || opts.oneResult)) {
              rows = null;
            } else if (opts.oneResult === true && rows.length > 0) {
                rows = rows[0];
            }
          }
          dbDone();
          if (callback) callback(err, rows);
          return err ? reject(err) : resolve(rows);
        });
      });
    });
  };

  function prepArgs(args, callback, opts) {
    callback = typeof args === 'function' ? args : callback;
    args = typeof args === 'object' ? args : {};
    args = lodash.defaults(args, opts.defaults || {});
    opts.validateOpts = opts.validateOpts || null;
    if (opts.validate) {
      let valRes = Joi.validate(args, opts.validate, opts.validateOpts);
      if (valRes.error) {
        opts.validationError = valRes.error;
      } else {
        args = valRes.value;
      }
    }
    return {callback, args};
  }

  function prepQuery(func, args, inst, model, name) {
    let queries = func.call(args, args, inst, model);

    if (!Array.isArray(queries)) {
      queries = [queries];
    }

    queries = queries.map((query) => {

      //if knex query builder
      if (typeof query === 'object' && query.constructor.name === 'QueryBuilder') {
        let knexQuery = query.toSQL();
        query = {
          text: positionBindings(knexQuery.sql),
          values: knexQuery.bindings
        };
      }
      if (typeof query === 'string') {
        query = {text: query};
      }
      return query;
    });
    return queries;
  }

  this.prepOpts = function (opts) {
    if (!opts.model) {
      opts.model = this;
    } else if (typeof opts.model === 'string') {
      opts.model = model_cache[opts.model];
    }
    return opts;
  };

  this.registerFactorySQL = function (opts) {
    if (typeof this[opts.name] !== 'undefined') {
      throw new Error(`Gatepost Model "${this.options.name}" already has a property named "${opts.name}"`);
    }
    opts = this.prepOpts(opts);
    this[opts.name] = (args, callback) => {
      let config = prepArgs(args, callback, opts, this);
      let query = prepQuery(opts.sql, config.args, null, this, opts.name);
      return this.runQuery(opts, query, config.callback);
    };
  };

  this.registerInstanceSQL = function (opts) {
    if (typeof this.controllers[opts.name] !== 'undefined') {
      throw new Error(`Instances of Gatepost Model "${this.options.name}" already have a property named "${opts.name}"`);
    }
    let extension = {};
    opts = this.prepOpts(opts);
    extension[opts.name] = function (args, callback) {
      let config = prepArgs(args, callback, opts);
      let errors = this.doValidate();
      if (errors.error !== null) {
        opts.validationError = errors.error;
      }
      let query = prepQuery(opts.sql, config.args, this, this.__verymeta.model, `inst-${opts.name}`);
      return this.__verymeta.model.runQuery(opts, query, config.callback);
    };
    this.extendModel(extension);
  };

}).call(Model.prototype);

module.exports = {
  setConnection: function (connection) {
    default_connection = connection;
  },
  Model: Model,
  getClient: function (callback) {
    pg.connect(default_connection, callback);
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright 2017 Pier 1 Imports, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
  'rules': {
    // The rules below are listed in the order they appear on the eslint
    // rules page. All rules are listed to make it easier to keep in sync
    // as new ESLint rules are added.
    // http://eslint.org/docs/rules/
    // - Rules in the `eslint:recommended` ruleset that aren't listed but commented out (so
    //   they don't override a base ruleset).
    // - Rules that are recommended but contradict Pier 1 Imports
    //   are explicitly set to the Pier 1 Imports value.

    // Possible Errors
    // http://eslint.org/docs/rules/#possible-errors
    // ---------------------------------------------
    // 'no-cond-assign': 2,
    // 'no-console': 2,
    // 'no-constant-condition': 2,
    // 'no-control-regex': 2,
    // 'no-debugger': 2,
    // 'no-dupe-args': 2,
    // 'no-dupe-keys': 2,
    // 'no-duplicate-case': 2,
    // 'no-empty-character-class': 2,
    // 'no-empty': 2,
    // 'no-ex-assign': 2,
    // 'no-extra-boolean-cast': 2,
    // 'no-extra-parens': 0,
    // 'no-extra-semi': 2,
    // 'no-func-assign': 2,
    // 'no-inner-declarations': 2,
    // 'no-invalid-regexp': 2,
    // 'no-irregular-whitespace': 2,
    // 'no-obj-calls': 2,
    // 'no-prototype-builtins': 0,
    // 'no-regex-spaces': 2,
    // 'no-sparse-arrays': 2,
    // 'no-template-curly-in-string': 0,
    // 'no-unexpected-multiline': 2,
    // 'no-unreachable': 2,
    // 'no-unsafe-finally': 2,
    // 'no-unsafe-negation': 0,
    // 'use-isnan': 2
    // 'valid-jsdoc': [
    //   1, {
    //     requireParamDescription: false,
    //     requireReturnDescription: false,
    //     requireReturn: false,
    //     prefer: { returns: 'return' },
    //   }
    // ],
    // 'valid-typeof': 2

    // Best Practices
    // http://eslint.org/docs/rules/#best-practices
    // --------------------------------------------

    // 'accessor-pairs': 0,
    // 'array-callback-return': 0,
    // 'block-scoped-var': 0,
    // 'class-methods-use-this': 0,
    // 'complexity': 0,
    // 'consistent-return': 0
    // 'curly': 0,
    // 'default-case': 0,
    // 'dot-location': 0,
    // 'dot-notation': 0,
    // 'eqeqeq': 0,
    'guard-for-in': 2,
    // 'no-alert': 0,
    'no-caller': 2,
    // 'no-case-declarations': 2,
    // 'no-div-regex': 0,
    // 'no-else-return': 0,
    // 'no-empty-function': 0,
    // 'no-empty-pattern': 2,
    // 'no-eq-null': 0,
    // 'no-eval': 0,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    // 'no-extra-label': 0,
    // 'no-fallthrough': 2,
    // 'no-floating-decimal': 0,
    // 'no-global-assign': 0,
    // 'no-implicit-coercion': 0,
    // 'no-implicit-globals': 0,
    // 'no-implied-eval': 0,
    'no-invalid-this': 2,
    // 'no-iterator': 0,
    // 'no-labels': 0,
    // 'no-lone-blocks': 0,
    // 'no-loop-func': 0,
    // 'no-magic-numbers': 0,
    'no-multi-spaces': 2,
    'no-multi-str': 0,
    // 'no-new-func': 0,
    'no-new-wrappers': 2,
    // 'no-new': 0,
    // 'no-octal-escape': 0,
    // 'no-octal': 2,
    // 'no-param-reassign': 0,
    // 'no-proto': 0,
    // 'no-redeclare': 2,
    // 'no-return-assign': 0,
    // 'no-script-url': 0,
    // 'no-self-assign': 2,
    // 'no-self-compare': 0,
    // 'no-sequences': 0,
    'no-throw-literal': 2,
    // 'no-unmodified-loop-condition': 0,
    // 'no-unused-expressions': 0,
    // 'no-unused-labels': 2,
    // 'no-useless-call': 0,
    // 'no-useless-concat': 0,
    // 'no-useless-escape': 0,
    // 'no-void': 0,
    // 'no-warning-comments': 0,
    'no-with': 2,
    // 'radix': 0,
    // 'vars-on-top': 0,
    // 'wrap-iife': 0,
    // 'yoda': 0,

    // Strict Mode
    // http://eslint.org/docs/rules/#strict-mode
    // -----------------------------------------
    // 'script': 0,

    // Variables
    // http://eslint.org/docs/rules/#variables
    // ---------------------------------------
    // 'init-declarations': 0,
    // 'no-catch-shadow': 0,
    // 'no-delete-var': 2,
    // 'no-label-var': 0,
    // 'no-restricted-globals': 0,
    // 'no-shadow-restricted-names': 0,
    // 'no-shadow': 0,
    // 'no-undef-init': 0,
    // 'no-undef': 2,
    // 'no-undefined': 0,
    'no-unused-vars': [
      1, {
        'vars': 'local',
        'args': 'none',
        'varsIgnorePattern': 'execute',
      }
    ],
    // 'no-use-before-define': 0,

    // Node.js and CommonJS
    // http://eslint.org/docs/rules/#nodejs-and-commonjs
    // -------------------------------------------------
    // 'callback-return': 0,
    // 'global-require': 0,
    // 'handle-callback-err': 0,
    // 'no-mixed-requires': 0,
    // 'no-new-require': 0,
    // 'no-path-concat': 0,
    // 'no-process-env': 0,
    // 'no-process-exit': 0,
    // 'no-restricted-modules': 0,
    // 'no-restricted-properties': 0,
    // 'no-sync': 0,

    // Stylistic Issues
    // http://eslint.org/docs/rules/#stylistic-issues
    // ----------------------------------------------
    'array-bracket-spacing': [2, 'never'],
    // 'block-spacing': 0,
    'brace-style': [2, '1tbs'],
    'camelcase': [2, { properties: 'always' }],
    'comma-dangle': [2, 'only-multiline'],
    'comma-spacing': 2,
    'comma-style': 2,
    'computed-property-spacing': 2,
    // 'consistent-this': 0,
    'eol-last': 2,
    'func-call-spacing': 2,
    // 'func-name-matching': 0,
    // 'func-names': 0,
    // 'func-style': 0,
    // 'id-blacklist': 0,
    // 'id-length': 0,
    // 'id-match': 0,
    // 'indent': 0,
    // 'jsx-quotes': 0,
    'key-spacing': 2,
    'keyword-spacing': 2,
    // 'line-comment-position': 0,
    'linebreak-style': 0,
    // 'lines-around-comment': 0,
    // 'lines-around-directive': 0,
    // 'max-depth': 0,
    'max-len': [
      1, {
        code: 100,
        tabWidth: 2,
        ignoreUrls: true,
        ignorePattern: '',
      }
    ],
    // 'max-lines': 0,
    // 'max-nested-callbacks': 0,
    // 'max-params': 0,
    // 'max-statements-per-line': 0,
    // 'max-statements': 0,
    // 'multiline-ternary': 0,
    'new-cap': [
      2, {
        'newIsCap': true,
        'capIsNew': false,
        'properties': true
      }
    ],
    // 'new-parens': 0,
    // 'newline-after-var': 0,
    // 'newline-before-return': 0,
    // 'newline-per-chained-call': 0,
    'no-array-constructor': 2,
    // 'no-bitwise': 0,
    // 'no-continue': 0,
    // 'no-inline-comments': 0,
    // 'no-lonely-if': 0,
    // 'no-mixed-operators': 0,
    'no-mixed-spaces-and-tabs': 2,
    'no-multiple-empty-lines': [2, { max: 2 }],
    // 'no-negated-condition': 0,
    // 'no-nested-ternary': 0,
    'no-new-object': 2,
    // 'no-plusplus': 0,
    // 'no-restricted-syntax': 0,
    // 'no-tabs': 0,
    // 'no-ternary': 0,
    // 'no-trailing-spaces': 0,
    // 'no-underscore-dangle': 0,
    // 'no-unneeded-ternary': 0,
    // 'no-whitespace-before-property': 0,
    // 'object-curly-newline': 0,
    'object-curly-spacing': 2,
    // 'object-property-newline': 0,
    // 'one-var-declaration-per-line': 0,
    'one-var': [
      1, {
        var: 'always',
        let: 'always',
        const: 'always',
      }
    ],
    // 'operator-assignment': 0,
    // 'operator-linebreak': 0,
    'padded-blocks': [2, 'never'],
    'quote-props': [2, 'consistent'],
    'quotes': [1, 'single', { allowTemplateLiterals: true }],
    // 'require-jsdoc': [
    //   1, {
    //     require: {
    //       FunctionDeclaration: true,
    //       MethodDefinition: true,
    //       ClassDeclaration: true,
    //     },
    //   }
    // ],
    'semi-spacing': 2,
    'semi': 2,
    // 'sort-keys': 0,
    // 'sort-vars': 0,
    'space-before-blocks': 2,
    'space-before-function-paren': [
      2, {
        'anonymous': 'always',
        'named': 'never',
        'asyncArrow': 'never'
      }
    ],
    // 'space-in-parens': 0,
    // 'space-infix-ops': 0,
    // 'space-unary-ops': 0,
    'spaced-comment': 0,
    // 'unicode-bom': 0,
    // 'wrap-regex': 0,

    // ECMAScript 6
    // http://eslint.org/docs/rules/#ecmascript-6
    // ------------------------------------------
    // 'arrow-body-style': 0,
    'arrow-parens': [2, 'always'],
    // 'arrow-spacing': 0,
    // 'constructor-super': 2,
    'generator-star-spacing': [2, 'after'],
    // 'no-class-assign': 0,
    // 'no-confusing-arrow': 0,
    // 'no-const-assign': 0,
    // 'no-dupe-class-members': 0,
    // 'no-duplicate-imports': 0,
    'no-new-symbol': 2,
    // 'no-restricted-imports': 0,
    // 'no-this-before-super': 2,
    // 'no-useless-computed-key': 0,
    // 'no-useless-constructor': 0,
    // 'no-useless-rename': 0,
    // 'no-var': 0,
    // 'object-shorthand': 0,
    // 'prefer-arrow-callback': 0,
    // 'prefer-const': 0,
    // 'prefer-numeric-literals': 0,
    // 'prefer-reflect': 0,
    'prefer-rest-params': 2,
    'prefer-spread': 2,
    // 'prefer-template': 0,
    // 'require-yield': 2,
    'rest-spread-spacing': 2,
    // 'sort-imports': 0,
    // 'symbol-description': 0,
    // 'template-curly-spacing': 0,
    'yield-star-spacing': [2, 'after'],
  },
  'env': {
    'browser': true,
    'commonjs': true,
    'es6': true,
    'jquery': true,
    'node': true,
    'mocha': true,
    'phantomjs': true,
  },
  'globals': {
    'ko': true,
    'module': true,

    /* Demandware Globals
     =============================== */
    'dw': true,
    'HTTPClient': true,
    'HTTPService': true,
    'importPackage': true,
    'PIPELET_NEXT': true,
    'PipelineDictionary': true,
    'request': true,
    'response': true,
    'session': true,
    'ServiceRegistry': true,
    'Site': true,
  },
  'parser': 'babel-eslint',
};
<commit_msg>Added Service to global ignore for Demandware<commit_after>/**
 * Copyright 2017 Pier 1 Imports, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

module.exports = {
  'rules': {
    // The rules below are listed in the order they appear on the eslint
    // rules page. All rules are listed to make it easier to keep in sync
    // as new ESLint rules are added.
    // http://eslint.org/docs/rules/
    // - Rules in the `eslint:recommended` ruleset that aren't listed but commented out (so
    //   they don't override a base ruleset).
    // - Rules that are recommended but contradict Pier 1 Imports
    //   are explicitly set to the Pier 1 Imports value.

    // Possible Errors
    // http://eslint.org/docs/rules/#possible-errors
    // ---------------------------------------------
    // 'no-cond-assign': 2,
    // 'no-console': 2,
    // 'no-constant-condition': 2,
    // 'no-control-regex': 2,
    // 'no-debugger': 2,
    // 'no-dupe-args': 2,
    // 'no-dupe-keys': 2,
    // 'no-duplicate-case': 2,
    // 'no-empty-character-class': 2,
    // 'no-empty': 2,
    // 'no-ex-assign': 2,
    // 'no-extra-boolean-cast': 2,
    // 'no-extra-parens': 0,
    // 'no-extra-semi': 2,
    // 'no-func-assign': 2,
    // 'no-inner-declarations': 2,
    // 'no-invalid-regexp': 2,
    // 'no-irregular-whitespace': 2,
    // 'no-obj-calls': 2,
    // 'no-prototype-builtins': 0,
    // 'no-regex-spaces': 2,
    // 'no-sparse-arrays': 2,
    // 'no-template-curly-in-string': 0,
    // 'no-unexpected-multiline': 2,
    // 'no-unreachable': 2,
    // 'no-unsafe-finally': 2,
    // 'no-unsafe-negation': 0,
    // 'use-isnan': 2
    // 'valid-jsdoc': [
    //   1, {
    //     requireParamDescription: false,
    //     requireReturnDescription: false,
    //     requireReturn: false,
    //     prefer: { returns: 'return' },
    //   }
    // ],
    // 'valid-typeof': 2

    // Best Practices
    // http://eslint.org/docs/rules/#best-practices
    // --------------------------------------------

    // 'accessor-pairs': 0,
    // 'array-callback-return': 0,
    // 'block-scoped-var': 0,
    // 'class-methods-use-this': 0,
    // 'complexity': 0,
    // 'consistent-return': 0
    // 'curly': 0,
    // 'default-case': 0,
    // 'dot-location': 0,
    // 'dot-notation': 0,
    // 'eqeqeq': 0,
    'guard-for-in': 2,
    // 'no-alert': 0,
    'no-caller': 2,
    // 'no-case-declarations': 2,
    // 'no-div-regex': 0,
    // 'no-else-return': 0,
    // 'no-empty-function': 0,
    // 'no-empty-pattern': 2,
    // 'no-eq-null': 0,
    // 'no-eval': 0,
    'no-extend-native': 2,
    'no-extra-bind': 2,
    // 'no-extra-label': 0,
    // 'no-fallthrough': 2,
    // 'no-floating-decimal': 0,
    // 'no-global-assign': 0,
    // 'no-implicit-coercion': 0,
    // 'no-implicit-globals': 0,
    // 'no-implied-eval': 0,
    'no-invalid-this': 2,
    // 'no-iterator': 0,
    // 'no-labels': 0,
    // 'no-lone-blocks': 0,
    // 'no-loop-func': 0,
    // 'no-magic-numbers': 0,
    'no-multi-spaces': 2,
    'no-multi-str': 0,
    // 'no-new-func': 0,
    'no-new-wrappers': 2,
    // 'no-new': 0,
    // 'no-octal-escape': 0,
    // 'no-octal': 2,
    // 'no-param-reassign': 0,
    // 'no-proto': 0,
    // 'no-redeclare': 2,
    // 'no-return-assign': 0,
    // 'no-script-url': 0,
    // 'no-self-assign': 2,
    // 'no-self-compare': 0,
    // 'no-sequences': 0,
    'no-throw-literal': 2,
    // 'no-unmodified-loop-condition': 0,
    // 'no-unused-expressions': 0,
    // 'no-unused-labels': 2,
    // 'no-useless-call': 0,
    // 'no-useless-concat': 0,
    // 'no-useless-escape': 0,
    // 'no-void': 0,
    // 'no-warning-comments': 0,
    'no-with': 2,
    // 'radix': 0,
    // 'vars-on-top': 0,
    // 'wrap-iife': 0,
    // 'yoda': 0,

    // Strict Mode
    // http://eslint.org/docs/rules/#strict-mode
    // -----------------------------------------
    // 'script': 0,

    // Variables
    // http://eslint.org/docs/rules/#variables
    // ---------------------------------------
    // 'init-declarations': 0,
    // 'no-catch-shadow': 0,
    // 'no-delete-var': 2,
    // 'no-label-var': 0,
    // 'no-restricted-globals': 0,
    // 'no-shadow-restricted-names': 0,
    // 'no-shadow': 0,
    // 'no-undef-init': 0,
    // 'no-undef': 2,
    // 'no-undefined': 0,
    'no-unused-vars': [
      1, {
        'vars': 'local',
        'args': 'none',
        'varsIgnorePattern': 'execute',
      }
    ],
    // 'no-use-before-define': 0,

    // Node.js and CommonJS
    // http://eslint.org/docs/rules/#nodejs-and-commonjs
    // -------------------------------------------------
    // 'callback-return': 0,
    // 'global-require': 0,
    // 'handle-callback-err': 0,
    // 'no-mixed-requires': 0,
    // 'no-new-require': 0,
    // 'no-path-concat': 0,
    // 'no-process-env': 0,
    // 'no-process-exit': 0,
    // 'no-restricted-modules': 0,
    // 'no-restricted-properties': 0,
    // 'no-sync': 0,

    // Stylistic Issues
    // http://eslint.org/docs/rules/#stylistic-issues
    // ----------------------------------------------
    'array-bracket-spacing': [2, 'never'],
    // 'block-spacing': 0,
    'brace-style': [2, '1tbs'],
    'camelcase': [2, { properties: 'always' }],
    'comma-dangle': [2, 'only-multiline'],
    'comma-spacing': 2,
    'comma-style': 2,
    'computed-property-spacing': 2,
    // 'consistent-this': 0,
    'eol-last': 2,
    'func-call-spacing': 2,
    // 'func-name-matching': 0,
    // 'func-names': 0,
    // 'func-style': 0,
    // 'id-blacklist': 0,
    // 'id-length': 0,
    // 'id-match': 0,
    // 'indent': 0,
    // 'jsx-quotes': 0,
    'key-spacing': 2,
    'keyword-spacing': 2,
    // 'line-comment-position': 0,
    'linebreak-style': 0,
    // 'lines-around-comment': 0,
    // 'lines-around-directive': 0,
    // 'max-depth': 0,
    'max-len': [
      1, {
        code: 100,
        tabWidth: 2,
        ignoreUrls: true,
        ignorePattern: '',
      }
    ],
    // 'max-lines': 0,
    // 'max-nested-callbacks': 0,
    // 'max-params': 0,
    // 'max-statements-per-line': 0,
    // 'max-statements': 0,
    // 'multiline-ternary': 0,
    'new-cap': [
      2, {
        'newIsCap': true,
        'capIsNew': false,
        'properties': true
      }
    ],
    // 'new-parens': 0,
    // 'newline-after-var': 0,
    // 'newline-before-return': 0,
    // 'newline-per-chained-call': 0,
    'no-array-constructor': 2,
    // 'no-bitwise': 0,
    // 'no-continue': 0,
    // 'no-inline-comments': 0,
    // 'no-lonely-if': 0,
    // 'no-mixed-operators': 0,
    'no-mixed-spaces-and-tabs': 2,
    'no-multiple-empty-lines': [2, { max: 2 }],
    // 'no-negated-condition': 0,
    // 'no-nested-ternary': 0,
    'no-new-object': 2,
    // 'no-plusplus': 0,
    // 'no-restricted-syntax': 0,
    // 'no-tabs': 0,
    // 'no-ternary': 0,
    // 'no-trailing-spaces': 0,
    // 'no-underscore-dangle': 0,
    // 'no-unneeded-ternary': 0,
    // 'no-whitespace-before-property': 0,
    // 'object-curly-newline': 0,
    'object-curly-spacing': 2,
    // 'object-property-newline': 0,
    // 'one-var-declaration-per-line': 0,
    'one-var': [
      1, {
        var: 'always',
        let: 'always',
        const: 'always',
      }
    ],
    // 'operator-assignment': 0,
    // 'operator-linebreak': 0,
    'padded-blocks': [2, 'never'],
    'quote-props': [2, 'consistent'],
    'quotes': [1, 'single', { allowTemplateLiterals: true }],
    // 'require-jsdoc': [
    //   1, {
    //     require: {
    //       FunctionDeclaration: true,
    //       MethodDefinition: true,
    //       ClassDeclaration: true,
    //     },
    //   }
    // ],
    'semi-spacing': 2,
    'semi': 2,
    // 'sort-keys': 0,
    // 'sort-vars': 0,
    'space-before-blocks': 2,
    'space-before-function-paren': [
      2, {
        'anonymous': 'always',
        'named': 'never',
        'asyncArrow': 'never'
      }
    ],
    // 'space-in-parens': 0,
    // 'space-infix-ops': 0,
    // 'space-unary-ops': 0,
    'spaced-comment': 0,
    // 'unicode-bom': 0,
    // 'wrap-regex': 0,

    // ECMAScript 6
    // http://eslint.org/docs/rules/#ecmascript-6
    // ------------------------------------------
    // 'arrow-body-style': 0,
    'arrow-parens': [2, 'always'],
    // 'arrow-spacing': 0,
    // 'constructor-super': 2,
    'generator-star-spacing': [2, 'after'],
    // 'no-class-assign': 0,
    // 'no-confusing-arrow': 0,
    // 'no-const-assign': 0,
    // 'no-dupe-class-members': 0,
    // 'no-duplicate-imports': 0,
    'no-new-symbol': 2,
    // 'no-restricted-imports': 0,
    // 'no-this-before-super': 2,
    // 'no-useless-computed-key': 0,
    // 'no-useless-constructor': 0,
    // 'no-useless-rename': 0,
    // 'no-var': 0,
    // 'object-shorthand': 0,
    // 'prefer-arrow-callback': 0,
    // 'prefer-const': 0,
    // 'prefer-numeric-literals': 0,
    // 'prefer-reflect': 0,
    'prefer-rest-params': 2,
    'prefer-spread': 2,
    // 'prefer-template': 0,
    // 'require-yield': 2,
    'rest-spread-spacing': 2,
    // 'sort-imports': 0,
    // 'symbol-description': 0,
    // 'template-curly-spacing': 0,
    'yield-star-spacing': [2, 'after'],
  },
  'env': {
    'browser': true,
    'commonjs': true,
    'es6': true,
    'jquery': true,
    'node': true,
    'mocha': true,
    'phantomjs': true,
  },
  'globals': {
    'ko': true,
    'module': true,

    /* Demandware Globals
     =============================== */
    'dw': true,
    'HTTPClient': true,
    'HTTPService': true,
    'importPackage': true,
    'PIPELET_NEXT': true,
    'PipelineDictionary': true,
    'request': true,
    'response': true,
    'session': true,
    'Service': true,
    'ServiceRegistry': true,
    'Site': true,
  },
  'parser': 'babel-eslint',
};
<|endoftext|>


<commit_before>/*!
 * @license
 * EME Encryption Scheme Polyfill
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
// This special header is retained in minified bundle, and only adds ~120 bytes.

/**
 * A polyfill to add support for EncryptionScheme queries in EME.
 *
 * Because this polyfill can't know what schemes the UA or CDM actually support,
 * it assumes support for the historically-supported schemes of each well-known
 * key system.
 *
 * In source form, this is compatible with the Closure Compiler, CommonJS, and
 * AMD module formats.  It can also be directly included via a script tag.
 *
 * The minified bundle is a standalone module compatible with the CommonJS and
 * AMD module formats, and can also be directly included via a script tag.
 *
 * @see https://wicg.github.io/encrypted-media-encryption-scheme/
 * @see https://github.com/w3c/encrypted-media/pull/457
 * @export
 */
class EmeEncryptionSchemePolyfill {
  /**
   * Installs the polyfill.  To avoid the possibility of extra user prompts,
   * this will shim EME so long as it exists, without checking support for
   * encryptionScheme upfront.  The support check will happen on-demand the
   * first time EME is used.
   *
   * @export
   */
  static install() {
    if (!navigator.requestMediaKeySystemAccess ||
        !MediaKeySystemAccess.prototype.getConfiguration) {
      console.debug('EmeEncryptionSchemePolyfill: EME not found');
      // No EME.
      return;
    }

    // Save the original.
    EmeEncryptionSchemePolyfill.originalRMKSA_ =
        navigator.requestMediaKeySystemAccess;

    // Patch in a method which will check for support on the first call.
    console.debug('EmeEncryptionSchemePolyfill: ' +
        'Waiting to detect encryptionScheme support.');
    navigator.requestMediaKeySystemAccess =
        EmeEncryptionSchemePolyfill.probeRMKSA_;
  }

  /**
   * Guess the supported encryption scheme for the key system.
   *
   * @param {string} keySystem The key system ID.
   * @return {?string} A guess at the encryption scheme this key system
   *   supports.
   * @private
   */
  static guessSupportedScheme_(keySystem) {
    if (keySystem.startsWith('com.widevine')) {
      return 'cenc';
    } else if (keySystem.startsWith('com.microsoft')) {
      return 'cenc';
    } else if (keySystem.startsWith('com.adobe')) {
      return 'cenc';
    } else if (keySystem.startsWith('org.w3')) {
      return 'cenc';
    } else if (keySystem.startsWith('com.apple')) {
      return 'cbcs-recommended';
    }

    // We don't have this key system in our map!

    // Log a warning.  The only way the request will succeed now is if the
    // app doesn't specify an encryption scheme in their own configs.
    // Use bracket notation to keep this from being stripped from the build.
    console['warn']('EmeEncryptionSchemePolyfill: Unknown key system:',
        keySystem, 'Please contribute!');

    return null;
  }

  /**
   * A shim for navigator.requestMediaKeySystemAccess to check for
   * encryptionScheme support.  Only used until we know if the browser has
   * native support for the encryptionScheme field.
   *
   * @this {Navigator}
   * @param {string} keySystem The key system ID.
   * @param {!Array.<!MediaKeySystemConfiguration>} supportedConfigurations An
   *   array of supported configurations the application can use.
   * @return {!Promise.<!MediaKeySystemAccess>} A Promise to a
   *   MediaKeySystemAccess instance.
   * @private
   */
  static async probeRMKSA_(keySystem, supportedConfigurations) {
    console.assert(this == navigator,
        'bad "this" for requestMediaKeySystemAccess');

    // Call the original version.  If the call succeeds, we look at the result
    // to decide if the encryptionScheme field is supported or not.
    const mediaKeySystemAccess =
        await EmeEncryptionSchemePolyfill.originalRMKSA_.call(
            this, keySystem, supportedConfigurations);

    const configuration = mediaKeySystemAccess.getConfiguration();

    // It doesn't matter which capability we look at.  For this check, they
    // should all produce the same result.
    const firstVideoCapability =
        configuration.videoCapabilities && configuration.videoCapabilities[0];
    const firstAudioCapability =
        configuration.audioCapabilities && configuration.audioCapabilities[0];
    const firstCapability = firstVideoCapability || firstAudioCapability;

    // If supported by the browser, the encryptionScheme field must appear in
    // the returned configuration, regardless of whether or not it was
    // specified in the supportedConfigurations given by the application.
    if (firstCapability.encryptionScheme !== undefined) {
      // The browser supports the encryptionScheme field!
      // No need for a patch.  Revert back to the original implementation.
      console.debug('EmeEncryptionSchemePolyfill: ' +
          'Native encryptionScheme support found.');
      // eslint-disable-next-line require-atomic-updates
      navigator.requestMediaKeySystemAccess =
          EmeEncryptionSchemePolyfill.originalRMKSA_;
      // Return the results, which are completely valid.
      return mediaKeySystemAccess;
    }

    // If we land here, the browser does _not_ support the encryptionScheme
    // field.  So we install another patch to check the encryptionScheme field
    // in future calls.
    console.debug('EmeEncryptionSchemePolyfill: ' +
        'No native encryptionScheme support found. '+
        'Patching encryptionScheme support.');
    // eslint-disable-next-line require-atomic-updates
    navigator.requestMediaKeySystemAccess =
        EmeEncryptionSchemePolyfill.polyfillRMKSA_;

    // The results we have may not be valid.  Run the query again through our
    // polyfill.
    return EmeEncryptionSchemePolyfill.polyfillRMKSA_.call(
        this, keySystem, supportedConfigurations);
  }

  /**
   * A polyfill for navigator.requestMediaKeySystemAccess to handle the
   * encryptionScheme field in browsers that don't support it.  It uses the
   * user-agent string to guess what encryption schemes are supported, then
   * those guesses are used to filter videoCapabilities and audioCapabilities
   * and reject unsupported schemes.
   *
   * @this {Navigator}
   * @param {string} keySystem The key system ID.
   * @param {!Array.<!MediaKeySystemConfiguration>} supportedConfigurations An
   *   array of supported configurations the application can use.
   * @return {!Promise.<!MediaKeySystemAccess>} A Promise to a
   *   MediaKeySystemAccess instance.
   * @private
   */
  static async polyfillRMKSA_(keySystem, supportedConfigurations) {
    console.assert(this == navigator,
        'bad "this" for requestMediaKeySystemAccess');

    const supportedScheme = EmeEncryptionSchemePolyfill.guessSupportedScheme_(
        keySystem);

    // Filter the application's configurations based on our guess of what
    // encryption scheme is supported.
    const filteredSupportedConfigurations = [];
    for (const configuration of supportedConfigurations) {
      const filteredVideoCapabilities =
          EmeEncryptionSchemePolyfill.filterCapabilities_(
              configuration.videoCapabilities, supportedScheme);
      const filteredAudioCapabilities =
          EmeEncryptionSchemePolyfill.filterCapabilities_(
              configuration.audioCapabilities, supportedScheme);

      if (configuration.videoCapabilities &&
          configuration.videoCapabilities.length &&
          !filteredVideoCapabilities.length) {
        // We eliminated all of the video capabilities, so this configuration
        // is unusable.
        continue;
      }
      if (configuration.audioCapabilities &&
          configuration.audioCapabilities.length &&
          !filteredAudioCapabilities.length) {
        // We eliminated all of the audio capabilities, so this configuration
        // is unusable.
        continue;
      }

      // Recreate a clone of the configuration and modify that.  This way, we
      // don't modify the application-provided config objects.
      const clonedConfiguration = Object.assign({}, configuration);
      clonedConfiguration.videoCapabilities = filteredVideoCapabilities;
      clonedConfiguration.audioCapabilities = filteredAudioCapabilities;
      filteredSupportedConfigurations.push(clonedConfiguration);
    }

    if (!filteredSupportedConfigurations.length) {
      // None of the application's configurations passed our encryptionScheme
      // filters, so this request fails.

      // As spec'd, this should be a DOMException, but there is not a public
      // constructor for this in all browsers.  This should be close enough for
      // most applications.
      const unsupportedError = new Error(
          'Unsupported keySystem or supportedConfigurations.');
      unsupportedError.name = 'NotSupportedError';
      unsupportedError.code = DOMException.NOT_SUPPORTED_ERR;
      throw unsupportedError;
    }

    // At this point, we have some filtered configurations that we think could
    // work.  Pass this subset to the native version of RMKSA.
    const mediaKeySystemAccess =
        await EmeEncryptionSchemePolyfill.originalRMKSA_.call(
            this, keySystem, filteredSupportedConfigurations);
    // Wrap the MKSA object in ours to provide the missing field in the
    // returned configuration.
    return new EmeEncryptionSchemePolyfillMediaKeySystemAccess(
        mediaKeySystemAccess, supportedScheme);
  }

  /**
   * Filters out capabilities that don't match the supported encryption scheme.
   *
   * @param {!Array.<MediaKeySystemMediaCapability>|undefined} capabilities
   *   An array of capabilities, or null or undefined.
   * @param {?string} supportedScheme The encryption scheme that we think is
   *   supported by the key system.
   * @return {!Array.<MediaKeySystemMediaCapability>|undefined} A filtered
   *   array of capabilities based on |supportedScheme|.  May be undefined if
   *   the input was undefined.
   * @private
   */
  static filterCapabilities_(capabilities, supportedScheme) {
    if (!capabilities) {
      return capabilities;
    }

    return capabilities.filter((capability) => {
      // No specific scheme always works.  In addition, accept the specific
      // scheme we guessed for this UA.
      return !capability.encryptionScheme ||
          capability.encryptionScheme == supportedScheme;
    });
  }
}

/**
 * A wrapper around MediaKeySystemAccess that adds encryptionScheme
 *   fields to the configuration, to emulate what a browser with native support
 *   for this field would do.
 *
 * @see https://github.com/w3c/encrypted-media/pull/457
 * @see https://github.com/WICG/encrypted-media-encryption-scheme/issues/13
 * @implements {MediaKeySystemAccess}
 */
class EmeEncryptionSchemePolyfillMediaKeySystemAccess {
  /**
   * @param {!MediaKeySystemAccess} mksa A native MediaKeySystemAccess instance
   *   to wrap.
   * @param {?string} scheme The encryption scheme to add to the configuration.
   */
  constructor(mksa, scheme) {
    /**
     * @const {!MediaKeySystemAccess}
     * @private
     */
    this.mksa_ = mksa;

    /**
     * @const {?string}
     * @private
     */
    this.scheme_ = scheme;

    /** @const {string} */
    this.keySystem = mksa.keySystem;
  }

  /** @override */
  getConfiguration() {
    // A browser which supports the encryptionScheme field would always return
    // that field in the resulting configuration.  So here, we emulate that.
    const configuration = this.mksa_.getConfiguration();

    if (configuration.videoCapabilities) {
      for (const capability of configuration.videoCapabilities) {
        capability.encryptionScheme = this.scheme_;
      }
    }

    if (configuration.audioCapabilities) {
      for (const capability of configuration.audioCapabilities) {
        capability.encryptionScheme = this.scheme_;
      }
    }

    return configuration;
  }

  /** @override */
  createMediaKeys() {
    return this.mksa_.createMediaKeys();
  }
}

/**
 * The original requestMediaKeySystemAccess, before we patched it.
 *
 * @type {
 *   function(this:Navigator,
 *     string,
 *     !Array.<!MediaKeySystemConfiguration>
 *   ):!Promise.<!MediaKeySystemAccess>
 * }
 * @private
 */
EmeEncryptionSchemePolyfill.originalRMKSA_;

// Support for CommonJS and AMD module formats.
/** @suppress {undefinedVars} */
(() => {
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = EmeEncryptionSchemePolyfill;
  }
})();
<commit_msg>Fix mis-translation by babel (#7)<commit_after>/*!
 * @license
 * EME Encryption Scheme Polyfill
 * Copyright 2019 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
// This special header is retained in minified bundle, and only adds ~120 bytes.

/**
 * A polyfill to add support for EncryptionScheme queries in EME.
 *
 * Because this polyfill can't know what schemes the UA or CDM actually support,
 * it assumes support for the historically-supported schemes of each well-known
 * key system.
 *
 * In source form, this is compatible with the Closure Compiler, CommonJS, and
 * AMD module formats.  It can also be directly included via a script tag.
 *
 * The minified bundle is a standalone module compatible with the CommonJS and
 * AMD module formats, and can also be directly included via a script tag.
 *
 * @see https://wicg.github.io/encrypted-media-encryption-scheme/
 * @see https://github.com/w3c/encrypted-media/pull/457
 * @export
 */
class EmeEncryptionSchemePolyfill {
  /**
   * Installs the polyfill.  To avoid the possibility of extra user prompts,
   * this will shim EME so long as it exists, without checking support for
   * encryptionScheme upfront.  The support check will happen on-demand the
   * first time EME is used.
   *
   * @export
   */
  static install() {
    if (!navigator.requestMediaKeySystemAccess ||
        !MediaKeySystemAccess.prototype.getConfiguration) {
      console.debug('EmeEncryptionSchemePolyfill: EME not found');
      // No EME.
      return;
    }

    // Save the original.
    EmeEncryptionSchemePolyfill.originalRMKSA_ =
        navigator.requestMediaKeySystemAccess;

    // Patch in a method which will check for support on the first call.
    console.debug('EmeEncryptionSchemePolyfill: ' +
        'Waiting to detect encryptionScheme support.');
    navigator.requestMediaKeySystemAccess =
        EmeEncryptionSchemePolyfill.probeRMKSA_;
  }

  /**
   * Guess the supported encryption scheme for the key system.
   *
   * @param {string} keySystem The key system ID.
   * @return {?string} A guess at the encryption scheme this key system
   *   supports.
   * @private
   */
  static guessSupportedScheme_(keySystem) {
    if (keySystem.startsWith('com.widevine')) {
      return 'cenc';
    } else if (keySystem.startsWith('com.microsoft')) {
      return 'cenc';
    } else if (keySystem.startsWith('com.adobe')) {
      return 'cenc';
    } else if (keySystem.startsWith('org.w3')) {
      return 'cenc';
    } else if (keySystem.startsWith('com.apple')) {
      return 'cbcs-recommended';
    }

    // We don't have this key system in our map!

    // Log a warning.  The only way the request will succeed now is if the
    // app doesn't specify an encryption scheme in their own configs.
    // Use bracket notation to keep this from being stripped from the build.
    console['warn']('EmeEncryptionSchemePolyfill: Unknown key system:',
        keySystem, 'Please contribute!');

    return null;
  }

  /**
   * A shim for navigator.requestMediaKeySystemAccess to check for
   * encryptionScheme support.  Only used until we know if the browser has
   * native support for the encryptionScheme field.
   *
   * @this {Navigator}
   * @param {string} keySystem The key system ID.
   * @param {!Array.<!MediaKeySystemConfiguration>} supportedConfigurations An
   *   array of supported configurations the application can use.
   * @return {!Promise.<!MediaKeySystemAccess>} A Promise to a
   *   MediaKeySystemAccess instance.
   * @private
   */
  static async probeRMKSA_(keySystem, supportedConfigurations) {
    console.assert(this == navigator,
        'bad "this" for requestMediaKeySystemAccess');

    // Call the original version.  If the call succeeds, we look at the result
    // to decide if the encryptionScheme field is supported or not.
    const mediaKeySystemAccess =
        await EmeEncryptionSchemePolyfill.originalRMKSA_.call(
            this, keySystem, supportedConfigurations);

    const configuration = mediaKeySystemAccess.getConfiguration();

    // It doesn't matter which capability we look at.  For this check, they
    // should all produce the same result.
    const firstVideoCapability =
        configuration.videoCapabilities && configuration.videoCapabilities[0];
    const firstAudioCapability =
        configuration.audioCapabilities && configuration.audioCapabilities[0];
    const firstCapability = firstVideoCapability || firstAudioCapability;

    // If supported by the browser, the encryptionScheme field must appear in
    // the returned configuration, regardless of whether or not it was
    // specified in the supportedConfigurations given by the application.
    if (firstCapability.encryptionScheme !== undefined) {
      // The browser supports the encryptionScheme field!
      // No need for a patch.  Revert back to the original implementation.
      console.debug('EmeEncryptionSchemePolyfill: ' +
          'Native encryptionScheme support found.');
      // eslint-disable-next-line require-atomic-updates
      navigator.requestMediaKeySystemAccess =
          EmeEncryptionSchemePolyfill.originalRMKSA_;
      // Return the results, which are completely valid.
      return mediaKeySystemAccess;
    }

    // If we land here, the browser does _not_ support the encryptionScheme
    // field.  So we install another patch to check the encryptionScheme field
    // in future calls.
    console.debug('EmeEncryptionSchemePolyfill: ' +
        'No native encryptionScheme support found. '+
        'Patching encryptionScheme support.');
    // eslint-disable-next-line require-atomic-updates
    navigator.requestMediaKeySystemAccess =
        EmeEncryptionSchemePolyfill.polyfillRMKSA_;

    // The results we have may not be valid.  Run the query again through our
    // polyfill.
    return EmeEncryptionSchemePolyfill.polyfillRMKSA_.call(
        this, keySystem, supportedConfigurations);
  }

  /**
   * A polyfill for navigator.requestMediaKeySystemAccess to handle the
   * encryptionScheme field in browsers that don't support it.  It uses the
   * user-agent string to guess what encryption schemes are supported, then
   * those guesses are used to filter videoCapabilities and audioCapabilities
   * and reject unsupported schemes.
   *
   * @this {Navigator}
   * @param {string} keySystem The key system ID.
   * @param {!Array.<!MediaKeySystemConfiguration>} supportedConfigurations An
   *   array of supported configurations the application can use.
   * @return {!Promise.<!MediaKeySystemAccess>} A Promise to a
   *   MediaKeySystemAccess instance.
   * @private
   */
  static async polyfillRMKSA_(keySystem, supportedConfigurations) {
    console.assert(this == navigator,
        'bad "this" for requestMediaKeySystemAccess');

    const supportedScheme = EmeEncryptionSchemePolyfill.guessSupportedScheme_(
        keySystem);

    // Filter the application's configurations based on our guess of what
    // encryption scheme is supported.
    const filteredSupportedConfigurations = [];
    for (const configuration of supportedConfigurations) {
      const filteredVideoCapabilities =
          EmeEncryptionSchemePolyfill.filterCapabilities_(
              configuration.videoCapabilities, supportedScheme);
      const filteredAudioCapabilities =
          EmeEncryptionSchemePolyfill.filterCapabilities_(
              configuration.audioCapabilities, supportedScheme);

      if (configuration.videoCapabilities &&
          configuration.videoCapabilities.length &&
          !filteredVideoCapabilities.length) {
        // We eliminated all of the video capabilities, so this configuration
        // is unusable.
      } else if (configuration.audioCapabilities &&
          configuration.audioCapabilities.length &&
          !filteredAudioCapabilities.length) {
        // We eliminated all of the audio capabilities, so this configuration
        // is unusable.
      } else {
        // Recreate a clone of the configuration and modify that.  This way, we
        // don't modify the application-provided config objects.
        const clonedConfiguration = Object.assign({}, configuration);
        clonedConfiguration.videoCapabilities = filteredVideoCapabilities;
        clonedConfiguration.audioCapabilities = filteredAudioCapabilities;
        filteredSupportedConfigurations.push(clonedConfiguration);
      }
    }

    if (!filteredSupportedConfigurations.length) {
      // None of the application's configurations passed our encryptionScheme
      // filters, so this request fails.

      // As spec'd, this should be a DOMException, but there is not a public
      // constructor for this in all browsers.  This should be close enough for
      // most applications.
      const unsupportedError = new Error(
          'Unsupported keySystem or supportedConfigurations.');
      unsupportedError.name = 'NotSupportedError';
      unsupportedError.code = DOMException.NOT_SUPPORTED_ERR;
      throw unsupportedError;
    }

    // At this point, we have some filtered configurations that we think could
    // work.  Pass this subset to the native version of RMKSA.
    const mediaKeySystemAccess =
        await EmeEncryptionSchemePolyfill.originalRMKSA_.call(
            this, keySystem, filteredSupportedConfigurations);
    // Wrap the MKSA object in ours to provide the missing field in the
    // returned configuration.
    return new EmeEncryptionSchemePolyfillMediaKeySystemAccess(
        mediaKeySystemAccess, supportedScheme);
  }

  /**
   * Filters out capabilities that don't match the supported encryption scheme.
   *
   * @param {!Array.<MediaKeySystemMediaCapability>|undefined} capabilities
   *   An array of capabilities, or null or undefined.
   * @param {?string} supportedScheme The encryption scheme that we think is
   *   supported by the key system.
   * @return {!Array.<MediaKeySystemMediaCapability>|undefined} A filtered
   *   array of capabilities based on |supportedScheme|.  May be undefined if
   *   the input was undefined.
   * @private
   */
  static filterCapabilities_(capabilities, supportedScheme) {
    if (!capabilities) {
      return capabilities;
    }

    return capabilities.filter((capability) => {
      // No specific scheme always works.  In addition, accept the specific
      // scheme we guessed for this UA.
      return !capability.encryptionScheme ||
          capability.encryptionScheme == supportedScheme;
    });
  }
}

/**
 * A wrapper around MediaKeySystemAccess that adds encryptionScheme
 *   fields to the configuration, to emulate what a browser with native support
 *   for this field would do.
 *
 * @see https://github.com/w3c/encrypted-media/pull/457
 * @see https://github.com/WICG/encrypted-media-encryption-scheme/issues/13
 * @implements {MediaKeySystemAccess}
 */
class EmeEncryptionSchemePolyfillMediaKeySystemAccess {
  /**
   * @param {!MediaKeySystemAccess} mksa A native MediaKeySystemAccess instance
   *   to wrap.
   * @param {?string} scheme The encryption scheme to add to the configuration.
   */
  constructor(mksa, scheme) {
    /**
     * @const {!MediaKeySystemAccess}
     * @private
     */
    this.mksa_ = mksa;

    /**
     * @const {?string}
     * @private
     */
    this.scheme_ = scheme;

    /** @const {string} */
    this.keySystem = mksa.keySystem;
  }

  /** @override */
  getConfiguration() {
    // A browser which supports the encryptionScheme field would always return
    // that field in the resulting configuration.  So here, we emulate that.
    const configuration = this.mksa_.getConfiguration();

    if (configuration.videoCapabilities) {
      for (const capability of configuration.videoCapabilities) {
        capability.encryptionScheme = this.scheme_;
      }
    }

    if (configuration.audioCapabilities) {
      for (const capability of configuration.audioCapabilities) {
        capability.encryptionScheme = this.scheme_;
      }
    }

    return configuration;
  }

  /** @override */
  createMediaKeys() {
    return this.mksa_.createMediaKeys();
  }
}

/**
 * The original requestMediaKeySystemAccess, before we patched it.
 *
 * @type {
 *   function(this:Navigator,
 *     string,
 *     !Array.<!MediaKeySystemConfiguration>
 *   ):!Promise.<!MediaKeySystemAccess>
 * }
 * @private
 */
EmeEncryptionSchemePolyfill.originalRMKSA_;

// Support for CommonJS and AMD module formats.
/** @suppress {undefinedVars} */
(() => {
  if (typeof module !== 'undefined' && module.exports) {
    module.exports = EmeEncryptionSchemePolyfill;
  }
})();
<|endoftext|>


<commit_before>/*
 * espower-source - Power Assert instrumentor from source to source.
 *
 * https://github.com/twada/espower-source
 *
 * Copyright (c) 2014 Takuto Wada
 * Licensed under the MIT license.
 *   https://raw.github.com/twada/espower-source/master/MIT-LICENSE.txt
 */
var espower = require('espower'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    merge = require('lodash.merge'),
    sourceMap = require('convert-source-map');

function espowerSourceToSource(jsCode, filepath, options) {
    'use strict';

    var espowerOptions, modifiedAst, generatedOutput, code, map,
        jsAst = esprima.parse(jsCode, {tolerant: true, loc: true, tokens: true, source: filepath});
    espowerOptions = merge(merge(espower.defaultOptions(), options), {
        destructive: true,
        path: filepath,
        source: jsCode
    });
    modifiedAst = espower(jsAst, espowerOptions);
    generatedOutput = escodegen.generate(modifiedAst, {
        sourceMap: true,
        sourceMapWithCode: true
    });
    code = generatedOutput.code; // Generated source code
    map = sourceMap.fromJSON(generatedOutput.map);
    map.sourcemap.sourcesContent = [jsCode];
    return code + '\n' + map.toComment() + '\n';
}

module.exports = espowerSourceToSource;
<commit_msg>Refactor<commit_after>/**
 * espower-source - Power Assert instrumentor from source to source.
 *
 * https://github.com/twada/espower-source
 *
 * Copyright (c) 2014 Takuto Wada
 * Licensed under the MIT license.
 *   https://raw.github.com/twada/espower-source/master/MIT-LICENSE.txt
 */
var espower = require('espower'),
    esprima = require('esprima'),
    escodegen = require('escodegen'),
    merge = require('lodash.merge'),
    sourceMap = require('convert-source-map');

function espowerSourceToSource(jsCode, filepath, options) {
    'use strict';

    var jsAst, espowerOptions, modifiedAst, escodegenOutput, code, map;

    jsAst = esprima.parse(jsCode, {tolerant: true, loc: true, tokens: true, source: filepath});
    espowerOptions = merge(merge(espower.defaultOptions(), options), {
        destructive: true,
        path: filepath,
        source: jsCode
    });
    modifiedAst = espower(jsAst, espowerOptions);
    escodegenOutput = escodegen.generate(modifiedAst, {
        sourceMap: true,
        sourceMapWithCode: true
    });
    code = escodegenOutput.code; // Generated source code
    map = sourceMap.fromJSON(escodegenOutput.map);
    map.sourcemap.sourcesContent = [jsCode];
    return code + '\n' + map.toComment() + '\n';
}

module.exports = espowerSourceToSource;
<|endoftext|>