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

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

var videoUrl;
var videoName;
var videoTime = null;

var videos = [];
var videoCounter = 0;
var videoIteration = 0;
var bufferTime = 2000;

var pauseProgressTime;
var timeProgressPaused = 0;

var videoPaused;
var stayPaused;
var backRestart;

var loopTimer;
var progressTimer;

function Timer(callback, delay) {
  var id, started, remaining = delay, running;
  this.start = function() {
    running = true;
    started = new Date();
    id = window.setTimeout(callback, remaining);
  }
  this.pause = function() {
    running = false;
    window.clearTimeout(id);
    remaining -= new Date() - started;
  }
  this.getTimeLeft = function() {
    if (running) {
      this.pause();
      this.start();
    }
    return remaining;
  }
  this.getStateRunning = function() {
    return running;
  }
  this.start();
}

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) {
  $("tr:nth-child(" + i + ")").attr("id", "newSelected");
  $("tr.selected").removeClass("selected");
  $("#newSelected").addClass("selected");
  $("#newSelected").removeAttr("id");
}

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

function resetTimer(which) {
  if (which != 0) {
      which.pause();
    }
    which = 0;
}

var ActionTimers = function() {
  this.pause = function() {
    loopTimer.pause();
    progressTimer.pause();
    pauseProgressTime = new Date();
  }
  this.resume = function() {
    loopTimer.resume();
    timeProgressPaused = timeProgressPaused + (new Date() - pauseProgressTime);
    progressTimer.resume();
  }
  this.clear = function() {
    resetTimer(loopTimer);
    resetTimer(progressTimer);
    $("#progress").css("width", "0%");
    $("#currentTime").text("0:00");
  }
}
var actionTimers = new ActionTimers();

function videoProgress() {
  $("#videoTime").text(msConversion(videos[videoIteration]["time"] * 1000));
  var startTime = new Date() + bufferTime;
  function progressLoop() {
    var currentTime = new Date() - timeProgressPaused - startTime;
    var currentPercent = currentTime / (videos[videoIteration]["time"] * 1000) * 100;
    progressTimer = new Timer(function() {
      $("#progress").css("width", currentPercent + "%");
      $("#currentTime").text(msConversion(currentTime));
      progressLoop();
    }, 500);
  }
  progressLoop();
}

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

  var autoplay = "";
  if (!stayPaused) {
    autoplay = "?autoplay=1";
  }

  if (embedUrl.search(/file:\/\//i) == -1) {
    embedUrl = "https://www.youtube.com/embed/" + videos[videoIteration]["url"] + autoplay;
  }
  $("#youtube").attr("src", embedUrl);

  videoProgress();

  backRestart = false;
  window.setTimeout(function() {
    backRestart = true;
  }, 3000);
}

function loopVideo() {
  videoIteration++;
  playVideo();
  loopTimer = new Timer(function() {
    if (videoIteration < videoCounter) {
      actionTimers.clear();
      loopVideo();
    }
    else {
      actionTimers.clear();
      $("#youtube").attr("src", "");
      document.title = "Streamly";
    }
  }, (videos[videoIteration]["time"] * 1000) + bufferTime);
  if (stayPaused) {
    actionTimers.pause();
  }
}

function pauseVideo() {
  if (!videoPaused) {
    actionTimers.pause();
    videoPaused = true;
    if (videos[0] !== null && videos[0] !== undefined) {
      document.title = "Streamly - " + decodeURIComponent(videos[0]);
    }
  }
  else {
    actionTimers.resume();
    videoPaused = false;
    stayPaused = false;
    document.title = "Streamly - " + decodeURIComponent(videos[videoIteration]["name"]);
  }
  $("#pauseOverlay").css("display", "none");
  setTimeout(function(){
    $("#pauseOverlay").css("display", "block");
    $("#youtube").blur();
  }, 500);
}

function forwardVideo() {
  if (videoIteration + 1 <= videoCounter) {
    actionTimers.clear();

    if (videoPaused) {
      stayPaused = true;
    }
    loopVideo();
  }
}

function backVideo() {
  if (videoPaused) {
    stayPaused = true;
  }
  if (!backRestart) {
    if (videoIteration - 2 > -1) {
      videoIteration = videoIteration - 2;
      actionTimers.clear();
      loopVideo();
    }
  }
  else {
    videoIteration = videoIteration - 1;
    actionTimers.clear();
    loopVideo();
  }
}

function setPlaylist() {
  if (videos.length > 1) {
    var playlist = JSON.stringify(videos);
    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 = JSON.parse(playlist);
    videos = playlist;

    if (videos[0] != undefined) {
      $("#playlistNameBox").val(decodeURIComponent(videos[0]));
    }

    for (i = 1; i < videos.length; i++) {
      videoCounter = i;
      var printTime = msConversion(videos[videoCounter]["time"] * 1000);
      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 = $("
").html(videoName).text();
        videoName = videoName.trim();
      } catch(err) {
        videoName = prompt("Please enter the name of the video", "");
      }
      videoName = encodeURIComponent(videoName).replace(/%20/g, " ");
      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;
      }
    },
    complete: function(jqXHR, textStatus) {
      $("#inputBox").val("").attr("placeholder", placeholder);
      addVideo();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      videoName = prompt("Please enter the name of the video", "");

      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 / 1000;
  video["url"] = videoUrl.replace(/^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=/i, "");
  videos[videoCounter] = video;

  var printTime = msConversion(videoTime);

  addVideoToList(videoName, printTime);

  setPlaylist();

  if (videoCounter == 1 || loopTimer == 0) {
    loopVideo();
  }
}

function actionPlayVideo(element) {
  var index = $(".playButton").index(element);
  videoIteration = index;
  actionTimers.clear();
  loopVideo();
}

function actionRemoveVideo(element) {
  var index = $(".removeButton").index(element) + 1;
  if (index == videoIteration) {
    if (videoIteration + 1 <= videoCounter) {
      forwardVideo();
      videoIteration--;
    }
    else {
      actionTimers.clear();
      $("#youtube").attr("src", "");
      document.title = "Streamly";
      videoIteration--;
    }
  }
  else if (index < videoIteration) {
    videoIteration--;
  }
  videoCounter--;
  videos.splice(index, 1);
  $("tr:nth-child(" + index + ")").remove();
  setPlaylist();
}

function urlValidate(url) {
  var isValidYouTube = /^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=.+$/i;
  var isValidFile = /^file:\/\/.+$/i;

  url = url.trim();
  url = url.replace(/&list=.+/g, "");

  if (url.search(isValidYouTube) > -1 || url.search(isValidFile) > -1) {
    return url;
  }
  else {
    return false;
  }
}

function input(type) {
  var inputBox = $("#inputBox").val();
  var playlistNameBox = $("#playlistNameBox").val();
  switch (type) {
    case 0:
      if (inputBox != "") {
        window.open("https://www.youtube.com/results?search_query=" + inputBox.replace(/ /g, "+"));
        $("#inputBox").val("").attr("placeholder", placeholder);
      }
      break;
    case 1:
      if (inputBox != "") {
        inputBox = urlValidate(inputBox);
        if (inputBox) {
          videoUrl = inputBox;
          $("#inputBox").val("").attr("placeholder", "Loading video data from YouTube...");
          getVideoData();
        }
        else {
          alert("That video's URL seems broken\n\nTry copying it again, or drag and drop the video directly");
        }
      }
      break;
    case 2:
      if (playlistNameBox != "") {
        videos[0] = encodeURIComponent(playlistNameBox).replace(/%20/g, " ");
        setPlaylist();
      }
      else {
        videos[0] = undefined;
      }
      break;
  }
}

document.addEventListener("drop", function(event) {
  event.preventDefault();
  var data = event.dataTransfer.getData("URL");

  $("#inputBox").val(data);
  input(1);
});

document.addEventListener("dragover", function(event) {
  event.preventDefault();
});
<commit_msg>give it a roll<commit_after>var placeholder = "Search, drag and drop video, or paste its URL...";

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

var videoUrl;
var videoName;
var videoTime = null;

var videos = [];
var videoCounter = 0;
var videoIteration = 0;
var bufferTime = 2000;

var videoPaused;
var stayPaused;
var backRestart;

var loopTimer;
var progressTimer;

function Timer(callback, delay) {
  var id, started, remaining = delay, running;
  this.start = function() {
    running = true;
    started = new Date();
    id = window.setTimeout(callback, remaining);
  }
  this.pause = function() {
    running = false;
    window.clearTimeout(id);
    remaining -= new Date() - started;
  }
  this.getTimeLeft = function() {
    if (running) {
      this.pause();
      this.start();
    }
    return remaining;
  }
  this.getStateRunning = function() {
    return running;
  }
  this.start();
}

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) {
  $("tr:nth-child(" + i + ")").attr("id", "newSelected");
  $("tr.selected").removeClass("selected");
  $("#newSelected").addClass("selected");
  $("#newSelected").removeAttr("id");
}

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

function resetTimer(which) {
  if (which != 0) {
      which.pause();
    }
    which = 0;
}

var ActionTimers = function() {
  this.pause = function() {
    loopTimer.pause();
    progressTimer.pause();
  }
  this.resume = function() {
    loopTimer.resume();
    progressTimer.resume();
  }
  this.clear = function() {
    resetTimer(loopTimer);
    resetTimer(progressTimer);
    $("#progress").css("width", "0%");
    $("#currentTime").text("0:00");
  }
}
var actionTimers = new ActionTimers();

function videoProgress() {
  $("#videoTime").text(msConversion(videos[videoIteration]["time"] * 1000));
  function progressLoop() {
    var currentTime = (videos[videoIteration]["time"] * 1000) - loopTimer.getTimeLeft();
    var currentPercent = currentTime / (videos[videoIteration]["time"] * 1000) * 100;
    progressTimer = new Timer(function() {
      $("#progress").css("width", currentPercent + "%");
      $("#currentTime").text(msConversion(currentTime));
      progressLoop();
    }, 500);
  }
  progressLoop();
}

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

  var autoplay = "";
  if (!stayPaused) {
    autoplay = "?autoplay=1";
  }

  if (embedUrl.search(/file:\/\//i) == -1) {
    embedUrl = "https://www.youtube.com/embed/" + videos[videoIteration]["url"] + autoplay;
  }
  $("#youtube").attr("src", embedUrl);

  videoProgress();

  backRestart = false;
  window.setTimeout(function() {
    backRestart = true;
  }, 3000);
}

function loopVideo() {
  videoIteration++;
  playVideo();
  loopTimer = new Timer(function() {
    if (videoIteration < videoCounter) {
      actionTimers.clear();
      loopVideo();
    }
    else {
      actionTimers.clear();
      $("#youtube").attr("src", "");
      document.title = "Streamly";
    }
  }, (videos[videoIteration]["time"] * 1000) + bufferTime);
  if (stayPaused) {
    actionTimers.pause();
  }
}

function pauseVideo() {
  if (!videoPaused) {
    actionTimers.pause();
    videoPaused = true;
    if (videos[0] !== null && videos[0] !== undefined) {
      document.title = "Streamly - " + decodeURIComponent(videos[0]);
    }
  }
  else {
    actionTimers.resume();
    videoPaused = false;
    stayPaused = false;
    document.title = "Streamly - " + decodeURIComponent(videos[videoIteration]["name"]);
  }
  $("#pauseOverlay").css("display", "none");
  setTimeout(function(){
    $("#pauseOverlay").css("display", "block");
    $("#youtube").blur();
  }, 500);
}

function forwardVideo() {
  if (videoIteration + 1 <= videoCounter) {
    actionTimers.clear();

    if (videoPaused) {
      stayPaused = true;
    }
    loopVideo();
  }
}

function backVideo() {
  if (videoPaused) {
    stayPaused = true;
  }
  if (!backRestart) {
    if (videoIteration - 2 > -1) {
      videoIteration = videoIteration - 2;
      actionTimers.clear();
      loopVideo();
    }
  }
  else {
    videoIteration = videoIteration - 1;
    actionTimers.clear();
    loopVideo();
  }
}

function setPlaylist() {
  if (videos.length > 1) {
    var playlist = JSON.stringify(videos);
    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 = JSON.parse(playlist);
    videos = playlist;

    if (videos[0] != undefined) {
      $("#playlistNameBox").val(decodeURIComponent(videos[0]));
    }

    for (i = 1; i < videos.length; i++) {
      videoCounter = i;
      var printTime = msConversion(videos[videoCounter]["time"] * 1000);
      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 = $("
").html(videoName).text();
        videoName = videoName.trim();
      } catch(err) {
        videoName = prompt("Please enter the name of the video", "");
      }
      videoName = encodeURIComponent(videoName).replace(/%20/g, " ");
      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;
      }
    },
    complete: function(jqXHR, textStatus) {
      $("#inputBox").val("").attr("placeholder", placeholder);
      addVideo();
    },
    error: function(jqXHR, textStatus, errorThrown) {
      videoName = prompt("Please enter the name of the video", "");

      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 / 1000;
  video["url"] = videoUrl.replace(/^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=/i, "");
  videos[videoCounter] = video;

  var printTime = msConversion(videoTime);

  addVideoToList(videoName, printTime);

  setPlaylist();

  if (videoCounter == 1 || loopTimer == 0) {
    loopVideo();
  }
}

function actionPlayVideo(element) {
  var index = $(".playButton").index(element);
  videoIteration = index;
  actionTimers.clear();
  loopVideo();
}

function actionRemoveVideo(element) {
  var index = $(".removeButton").index(element) + 1;
  if (index == videoIteration) {
    if (videoIteration + 1 <= videoCounter) {
      forwardVideo();
      videoIteration--;
    }
    else {
      actionTimers.clear();
      $("#youtube").attr("src", "");
      document.title = "Streamly";
      videoIteration--;
    }
  }
  else if (index < videoIteration) {
    videoIteration--;
  }
  videoCounter--;
  videos.splice(index, 1);
  $("tr:nth-child(" + index + ")").remove();
  setPlaylist();
}

function urlValidate(url) {
  var isValidYouTube = /^htt(p|ps):\/\/www\.youtube\.com\/watch\?v=.+$/i;
  var isValidFile = /^file:\/\/.+$/i;

  url = url.trim();
  url = url.replace(/&list=.+/g, "");

  if (url.search(isValidYouTube) > -1 || url.search(isValidFile) > -1) {
    return url;
  }
  else {
    return false;
  }
}

function input(type) {
  var inputBox = $("#inputBox").val();
  var playlistNameBox = $("#playlistNameBox").val();
  switch (type) {
    case 0:
      if (inputBox != "") {
        window.open("https://www.youtube.com/results?search_query=" + inputBox.replace(/ /g, "+"));
        $("#inputBox").val("").attr("placeholder", placeholder);
      }
      break;
    case 1:
      if (inputBox != "") {
        inputBox = urlValidate(inputBox);
        if (inputBox) {
          videoUrl = inputBox;
          $("#inputBox").val("").attr("placeholder", "Loading video data from YouTube...");
          getVideoData();
        }
        else {
          alert("That video's URL seems broken\n\nTry copying it again, or drag and drop the video directly");
        }
      }
      break;
    case 2:
      if (playlistNameBox != "") {
        videos[0] = encodeURIComponent(playlistNameBox).replace(/%20/g, " ");
        setPlaylist();
      }
      else {
        videos[0] = undefined;
      }
      break;
  }
}

document.addEventListener("drop", function(event) {
  event.preventDefault();
  var data = event.dataTransfer.getData("URL");

  $("#inputBox").val(data);
  input(1);
});

document.addEventListener("dragover", function(event) {
  event.preventDefault();
});
<|endoftext|>


<commit_before>/**
 * index.js
 */
"use strict";
{
  /* api */
  const {
    ChildProcess, CmdArgs, Input, Output,
    convertUriToFilePath, createDir, createFile, getAbsPath,
    getFileNameFromFilePath, getFileTimestamp, isDir, isExecutable, isFile,
    removeDir, readFile,
  } = require("web-ext-native-msg");
  const {isString, throwErr} = require("./modules/common");
  const os = require("os");
  const path = require("path");
  const process = require("process");

  /* constants */
  const {
    EDITOR_CMD_ARGS, EDITOR_CONFIG_FILE, EDITOR_CONFIG_GET, EDITOR_CONFIG_RES,
    EDITOR_CONFIG_TS, EDITOR_FILE_POS, EDITOR_PATH, HOST, LABEL,
    LOCAL_FILE_VIEW, PROCESS_CHILD, TMP_FILES, TMP_FILES_PB,
    TMP_FILES_PB_REMOVE, TMP_FILE_CREATE, TMP_FILE_DATA_PORT,
    TMP_FILE_GET, TMP_FILE_RES,
  } = require("./modules/constant");
  const APP = `${process.pid}`;
  const CHAR = "utf8";
  const DIR_HOME = os.homedir();
  const PERM_DIR = 0o700;
  const PERM_FILE = 0o600;
  const TMPDIR = process.env.TMP || process.env.TMPDIR || process.env.TEMP ||
                 os.tmpdir();
  const TMPDIR_APP = [TMPDIR, LABEL, APP];
  const TMPDIR_FILES = [...TMPDIR_APP, TMP_FILES];
  const TMPDIR_FILES_PB = [...TMPDIR_APP, TMP_FILES_PB];

  /* variables */
  const vars = {
    editorPath: "",
    cmdArgs: [],
    fileAfterCmdArgs: false,
  };

  /**
   * host message
   * @param {*} message - message
   * @param {string} status - status
   * @returns {Object} - host message object
   */
  const hostMsg = (message, status) => ({
    [HOST]: {
      message, status,
      pid: APP,
    },
  });

  /**
   * handle rejection
   * @param {*} e - Error or any
   * @returns {boolean} - false
   */
  const handleReject = e => {
    e = (new Output()).encode(hostMsg(e, "error"));
    e && process.stdout.write(e);
    return false;
  };

  /* output */
  /**
   * write stdout
   * @param {*} msg - message
   * @returns {?Function} - write message to the Writable stream
   */
  const writeStdout = async msg => {
    msg = await (new Output()).encode(msg);
    return msg && process.stdout.write(msg) || null;
  };

  /**
   * port app status
   * @param {Array} arr - array of temporary directories
   * @returns {Promise.<Array>} - results of each handler
   */
  const portAppStatus = async (arr = []) => {
    const [tmpDir, tmpDirPb] = arr;
    const func = [];
    if (tmpDir && tmpDirPb) {
      func.push(writeStdout(hostMsg(EDITOR_CONFIG_GET, "ready")));
    } else {
      !tmpDir && func.push(writeStdout(
        hostMsg(`Failed to create ${path.join(TMPDIR_FILES)}.`, "warn")
      ));
      !tmpDirPb && func.push(writeStdout(
        hostMsg(`Failed to create ${path.join(TMPDIR_FILES_PB)}.`, "warn")
      ));
    }
    return Promise.all(func);
  };

  /**
   * port editor config
   * @param {string} data - editor config
   * @param {string} editorConfig - editor config file path
   * @returns {?AsyncFunction} - write stdout
   */
  const portEditorConfig = async (data, editorConfig) => {
    let msg;
    try {
      data = data && JSON.parse(data);
      if (data) {
        const {editorPath} = data;
        const editorName = await getFileNameFromFilePath(editorPath);
        const executable = await isExecutable(editorPath);
        const timestamp = await getFileTimestamp(editorConfig) || 0;
        const items = Object.keys(vars);
        for (const item of items) {
          const obj = data[item];
          switch (item) {
            case "editorPath":
              vars[item] = obj;
              break;
            case "cmdArgs":
              vars[item] = (new CmdArgs(...obj)).toArray();
              break;
            case "fileAfterCmdArgs":
              vars[item] = !!obj;
              break;
            default:
          }
        }
        msg = {
          [EDITOR_CONFIG_RES]: {
            editorConfig, editorName, executable,
            [EDITOR_CMD_ARGS]: (new CmdArgs(...vars.cmdArgs)).toString(),
            [EDITOR_CONFIG_TS]: timestamp,
            [EDITOR_FILE_POS]: vars.fileAfterCmdArgs,
            [EDITOR_PATH]: editorPath,
          },
        };
      }
    } catch (e) {
      msg = hostMsg(`${e}: ${editorConfig}`, "error");
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * port file data
   * @param {Object} obj - file data
   * @returns {?AsyncFunction} - write stdout
   */
  const portFileData = async (obj = {}) => {
    const msg = Object.keys(obj).length && {
      [TMP_FILE_DATA_PORT]: obj,
    };
    return msg && writeStdout(msg) || null;
  };

  /* child process */
  /**
   * spawn child process
   * @param {string} file - file path
   * @param {string} app - app path
   * @returns {ChildProcess|AsyncFunction} - child process / write stdout
   */
  const spawnChildProcess = async (file, app = vars.editorPath) => {
    if (await !isFile(file)) {
      return writeStdout(hostMsg(`${file} is not a file.`, "warn"));
    }
    if (await !isExecutable(app)) {
      return writeStdout(hostMsg(`${app} is not executable.`, "warn"));
    }
    const args = vars.cmdArgs || [];
    const pos = vars.fileAfterCmdArgs || false;
    const opt = {
      cwd: null,
      encoding: CHAR,
      env: process.env,
    };
    const proc = await (new ChildProcess(app, args, opt)).spawn(file, pos);
    proc.on("error", e => {
      e = (new Output()).encode(e);
      e && process.stderr.write(e);
    });
    proc.stderr.on("data", data => {
      if (data) {
        data = (new Output()).encode(
          hostMsg(`${data}: ${app}`, `${PROCESS_CHILD}_stderr`)
        );
        data && process.stdout.write(data);
      }
    });
    proc.stdout.on("data", data => {
      if (data) {
        data = (new Output()).encode(
          hostMsg(`${data}: ${app}`, `${PROCESS_CHILD}_stdout`)
        );
        data && process.stdout.write(data);
      }
    });
    return proc;
  };

  /* temporary files */
  /**
   * initialize private temporary directory
   * @param {boolean} bool - remove
   * @returns {?AsyncFunction} - write stdout
   */
  const initPrivateTmpDir = async bool => {
    let msg;
    if (bool) {
      const dir = path.join(...TMPDIR_FILES_PB);
      await removeDir(dir, TMPDIR);
      if (await isDir(dir)) {
        msg = hostMsg(`Failed to remove ${dir}.`, "warn");
      } else {
        const dPath = await createDir(TMPDIR_FILES_PB, PERM_DIR);
        dir !== dPath && (msg = hostMsg(`Failed to create ${dir}.`, "warn"));
      }
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * create temporary file
   * @param {Object} obj - temporary file data object
   * @returns {Object} - temporary file data
   */
  const createTmpFile = async (obj = {}) => {
    const {data, value} = obj;
    let filePath;
    if (data) {
      const {dir, fileName, host, tabId, windowId} = data;
      const arr = dir && windowId && tabId && host &&
                    [...TMPDIR_APP, dir, windowId, tabId, host];
      const dPath = arr && await createDir(arr, PERM_DIR);
      filePath = dPath === path.join(...arr) && fileName &&
                   await createFile(
                     path.join(dPath, fileName), value,
                     {encoding: CHAR, flag: "w", mode: PERM_FILE}
                   );
      filePath && (data.filePath = filePath);
    }
    return data && filePath && {data, filePath} || null;
  };

  /**
   * get temporary file
   * @param {Object} data - temporary file data
   * @returns {?AsyncFunction} - write stdout
   */
  const getTmpFile = async (data = {}) => {
    const {filePath} = data;
    let msg;
    if (await isFile(filePath)) {
      const value = await readFile(filePath, {encoding: CHAR, flag: "r"}) || "";
      data.timestamp = await getFileTimestamp(filePath) || 0;
      msg = {
        [TMP_FILE_RES]: {data, value},
      };
    } else {
      msg = hostMsg(`${filePath} is not a file.`, "warn");
    }
    return msg && writeStdout(msg) || null;
  };

  /* local files */
  /**
   * get editor config
   * @param {string} filePath - editor config file path
   * @returns {Promise.<Array>} - results of each handler
   */
  const getEditorConfig = async filePath => {
    const func = [];
    let editorConfigPath;
    if (await isString(filePath) && filePath.length) {
      editorConfigPath = getAbsPath(filePath);
    } else {
      editorConfigPath = path.resolve(path.join(".", EDITOR_CONFIG_FILE));
    }
    if (editorConfigPath && editorConfigPath.startsWith(DIR_HOME) &&
        await isFile(editorConfigPath)) {
      const data = await readFile(editorConfigPath, {
        encoding: CHAR, flag: "r",
      });
      func.push(portEditorConfig(data, editorConfigPath));
    } else {
      func.push(
        writeStdout(hostMsg(`${editorConfigPath} is not a file.`, "warn")),
        writeStdout({[EDITOR_CONFIG_RES]: null})
      );
    }
    return Promise.all(func);
  };

  /**
   * view local file
   * @param {string} uri - local file uri
   * @returns {?AsyncFunction} - spawn child process
   */
  const viewLocalFile = async uri => {
    let func;
    if (await isString(uri)) {
      const {protocol} = new URL(uri);
      if (protocol === "file:") {
        const file = await convertUriToFilePath(uri);
        if (file && isFile(file)) {
          func = spawnChildProcess(file);
        }
      }
    }
    return func || null;
  };

  /* handlers */
  /**
   * handle created temporary file
   * @param {Object} obj - temporary file data
   * @returns {Promise.<Array>} - results of each handler
   */
  const handleCreatedTmpFile = async (obj = {}) => {
    const {filePath} = obj;
    const func = [];
    if (await isFile(filePath)) {
      func.push(spawnChildProcess(filePath), portFileData(obj));
    }
    return Promise.all(func);
  };

  /**
   * handle message
   * @param {*} msg - message
   * @returns {Promise.<Array>} - results of each handler
   */
  const handleMsg = async msg => {
    const func = [];
    const items = msg && Object.keys(msg);
    if (items && items.length) {
      for (const item of items) {
        const obj = msg[item];
        switch (item) {
          case EDITOR_CONFIG_GET:
            func.push(getEditorConfig(obj));
            break;
          case LOCAL_FILE_VIEW:
            func.push(viewLocalFile(obj));
            break;
          case TMP_FILE_CREATE:
            func.push(createTmpFile(obj).then(handleCreatedTmpFile));
            break;
          case TMP_FILE_GET:
            func.push(getTmpFile(obj));
            break;
          case TMP_FILES_PB_REMOVE:
            func.push(initPrivateTmpDir(obj));
            break;
          default:
            func.push(
              writeStdout(hostMsg(`No handler found for ${item}.`, "warn"))
            );
        }
      }
    } else {
      func.push(writeStdout(hostMsg(`No handler found for ${msg}.`, "warn")));
    }
    return Promise.all(func);
  };

  /* input */
  const input = new Input();

  /**
   * read stdin
   * @param {string|Buffer} chunk - chunk
   * @returns {?Promise.<Array.<Promise>>} - composite a Promise chain
   */
  const readStdin = chunk => {
    const arr = input.decode(chunk);
    const func = [];
    Array.isArray(arr) && arr.length && arr.forEach(msg => {
      msg && func.push(handleMsg(msg));
    });
    return func.length && Promise.all(func).catch(handleReject) || null;
  };

  /* exit */
  /**
   * handle exit
   * @param {number} code - exit code
   * @returns {void}
   */
  const handleExit = code => {
    const msg = (new Output()).encode(hostMsg(`exit ${code || 0}`, "exit"));
    removeDir(path.join(...TMPDIR_APP), TMPDIR);
    msg && process.stdout.write(msg);
  };

  /* process */
  process.on("exit", handleExit);
  process.on("uncaughtException", throwErr);
  process.on("unhandleRejection", handleReject);
  process.stdin.on("data", readStdin);

  /* startup */
  Promise.all([
    createDir(TMPDIR_FILES, PERM_DIR),
    createDir(TMPDIR_FILES_PB, PERM_DIR),
  ]).then(portAppStatus).catch(handleReject);
}
<commit_msg>Update warning message<commit_after>/**
 * index.js
 */
"use strict";
{
  /* api */
  const {
    ChildProcess, CmdArgs, Input, Output,
    convertUriToFilePath, createDir, createFile, getAbsPath,
    getFileNameFromFilePath, getFileTimestamp, isDir, isExecutable, isFile,
    removeDir, readFile,
  } = require("web-ext-native-msg");
  const {isString, throwErr} = require("./modules/common");
  const os = require("os");
  const path = require("path");
  const process = require("process");

  /* constants */
  const {
    EDITOR_CMD_ARGS, EDITOR_CONFIG_FILE, EDITOR_CONFIG_GET, EDITOR_CONFIG_RES,
    EDITOR_CONFIG_TS, EDITOR_FILE_POS, EDITOR_PATH, HOST, LABEL,
    LOCAL_FILE_VIEW, PROCESS_CHILD, TMP_FILES, TMP_FILES_PB,
    TMP_FILES_PB_REMOVE, TMP_FILE_CREATE, TMP_FILE_DATA_PORT,
    TMP_FILE_GET, TMP_FILE_RES,
  } = require("./modules/constant");
  const APP = `${process.pid}`;
  const CHAR = "utf8";
  const DIR_HOME = os.homedir();
  const PERM_DIR = 0o700;
  const PERM_FILE = 0o600;
  const TMPDIR = process.env.TMP || process.env.TMPDIR || process.env.TEMP ||
                 os.tmpdir();
  const TMPDIR_APP = [TMPDIR, LABEL, APP];
  const TMPDIR_FILES = [...TMPDIR_APP, TMP_FILES];
  const TMPDIR_FILES_PB = [...TMPDIR_APP, TMP_FILES_PB];

  /* variables */
  const vars = {
    editorPath: "",
    cmdArgs: [],
    fileAfterCmdArgs: false,
  };

  /**
   * host message
   * @param {*} message - message
   * @param {string} status - status
   * @returns {Object} - host message object
   */
  const hostMsg = (message, status) => ({
    [HOST]: {
      message, status,
      pid: APP,
    },
  });

  /**
   * handle rejection
   * @param {*} e - Error or any
   * @returns {boolean} - false
   */
  const handleReject = e => {
    e = (new Output()).encode(hostMsg(e, "error"));
    e && process.stdout.write(e);
    return false;
  };

  /* output */
  /**
   * write stdout
   * @param {*} msg - message
   * @returns {?Function} - write message to the Writable stream
   */
  const writeStdout = async msg => {
    msg = await (new Output()).encode(msg);
    return msg && process.stdout.write(msg) || null;
  };

  /**
   * port app status
   * @param {Array} arr - array of temporary directories
   * @returns {Promise.<Array>} - results of each handler
   */
  const portAppStatus = async (arr = []) => {
    const [tmpDir, tmpDirPb] = arr;
    const func = [];
    if (tmpDir && tmpDirPb) {
      func.push(writeStdout(hostMsg(EDITOR_CONFIG_GET, "ready")));
    } else {
      !tmpDir && func.push(writeStdout(
        hostMsg(`Failed to create ${path.join(TMPDIR_FILES)}.`, "warn")
      ));
      !tmpDirPb && func.push(writeStdout(
        hostMsg(`Failed to create ${path.join(TMPDIR_FILES_PB)}.`, "warn")
      ));
    }
    return Promise.all(func);
  };

  /**
   * port editor config
   * @param {string} data - editor config
   * @param {string} editorConfig - editor config file path
   * @returns {?AsyncFunction} - write stdout
   */
  const portEditorConfig = async (data, editorConfig) => {
    let msg;
    try {
      data = data && JSON.parse(data);
      if (data) {
        const {editorPath} = data;
        const editorName = await getFileNameFromFilePath(editorPath);
        const executable = await isExecutable(editorPath);
        const timestamp = await getFileTimestamp(editorConfig) || 0;
        const items = Object.keys(vars);
        for (const item of items) {
          const obj = data[item];
          switch (item) {
            case "editorPath":
              vars[item] = obj;
              break;
            case "cmdArgs":
              vars[item] = (new CmdArgs(...obj)).toArray();
              break;
            case "fileAfterCmdArgs":
              vars[item] = !!obj;
              break;
            default:
          }
        }
        msg = {
          [EDITOR_CONFIG_RES]: {
            editorConfig, editorName, executable,
            [EDITOR_CMD_ARGS]: (new CmdArgs(...vars.cmdArgs)).toString(),
            [EDITOR_CONFIG_TS]: timestamp,
            [EDITOR_FILE_POS]: vars.fileAfterCmdArgs,
            [EDITOR_PATH]: editorPath,
          },
        };
      }
    } catch (e) {
      msg = hostMsg(`${e}: ${editorConfig}`, "error");
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * port file data
   * @param {Object} obj - file data
   * @returns {?AsyncFunction} - write stdout
   */
  const portFileData = async (obj = {}) => {
    const msg = Object.keys(obj).length && {
      [TMP_FILE_DATA_PORT]: obj,
    };
    return msg && writeStdout(msg) || null;
  };

  /* child process */
  /**
   * spawn child process
   * @param {string} file - file path
   * @param {string} app - app path
   * @returns {ChildProcess|AsyncFunction} - child process / write stdout
   */
  const spawnChildProcess = async (file, app = vars.editorPath) => {
    if (await !isFile(file)) {
      return writeStdout(hostMsg(`${file} is not a file.`, "warn"));
    }
    if (await !isExecutable(app)) {
      return writeStdout(hostMsg(`${app} is not executable.`, "warn"));
    }
    const args = vars.cmdArgs || [];
    const pos = vars.fileAfterCmdArgs || false;
    const opt = {
      cwd: null,
      encoding: CHAR,
      env: process.env,
    };
    const proc = await (new ChildProcess(app, args, opt)).spawn(file, pos);
    proc.on("error", e => {
      e = (new Output()).encode(e);
      e && process.stderr.write(e);
    });
    proc.stderr.on("data", data => {
      if (data) {
        data = (new Output()).encode(
          hostMsg(`${data}: ${app}`, `${PROCESS_CHILD}_stderr`)
        );
        data && process.stdout.write(data);
      }
    });
    proc.stdout.on("data", data => {
      if (data) {
        data = (new Output()).encode(
          hostMsg(`${data}: ${app}`, `${PROCESS_CHILD}_stdout`)
        );
        data && process.stdout.write(data);
      }
    });
    return proc;
  };

  /* temporary files */
  /**
   * initialize private temporary directory
   * @param {boolean} bool - remove
   * @returns {?AsyncFunction} - write stdout
   */
  const initPrivateTmpDir = async bool => {
    let msg;
    if (bool) {
      const dir = path.join(...TMPDIR_FILES_PB);
      await removeDir(dir, TMPDIR);
      if (await isDir(dir)) {
        msg = hostMsg(`Failed to remove ${dir}.`, "warn");
      } else {
        const dPath = await createDir(TMPDIR_FILES_PB, PERM_DIR);
        dir !== dPath && (msg = hostMsg(`Failed to create ${dir}.`, "warn"));
      }
    }
    return msg && writeStdout(msg) || null;
  };

  /**
   * create temporary file
   * @param {Object} obj - temporary file data object
   * @returns {Object} - temporary file data
   */
  const createTmpFile = async (obj = {}) => {
    const {data, value} = obj;
    let filePath;
    if (data) {
      const {dir, fileName, host, tabId, windowId} = data;
      const arr = dir && windowId && tabId && host &&
                    [...TMPDIR_APP, dir, windowId, tabId, host];
      const dPath = arr && await createDir(arr, PERM_DIR);
      filePath = dPath === path.join(...arr) && fileName &&
                   await createFile(
                     path.join(dPath, fileName), value,
                     {encoding: CHAR, flag: "w", mode: PERM_FILE}
                   );
      filePath && (data.filePath = filePath);
    }
    return data && filePath && {data, filePath} || null;
  };

  /**
   * get temporary file
   * @param {Object} data - temporary file data
   * @returns {?AsyncFunction} - write stdout
   */
  const getTmpFile = async (data = {}) => {
    const {filePath} = data;
    let msg;
    if (await isFile(filePath)) {
      const value = await readFile(filePath, {encoding: CHAR, flag: "r"}) || "";
      data.timestamp = await getFileTimestamp(filePath) || 0;
      msg = {
        [TMP_FILE_RES]: {data, value},
      };
    } else {
      msg = hostMsg(`${filePath} is not a file.`, "warn");
    }
    return msg && writeStdout(msg) || null;
  };

  /* local files */
  /**
   * get editor config
   * @param {string} filePath - editor config file path
   * @returns {Promise.<Array>} - results of each handler
   */
  const getEditorConfig = async filePath => {
    const func = [];
    let editorConfigPath;
    if (await isString(filePath) && filePath.length) {
      editorConfigPath = await getAbsPath(filePath);
    } else {
      editorConfigPath = path.resolve(path.join(".", EDITOR_CONFIG_FILE));
    }
    if (editorConfigPath && editorConfigPath.startsWith(DIR_HOME) &&
        await isFile(editorConfigPath)) {
      const data = await readFile(editorConfigPath, {
        encoding: CHAR, flag: "r",
      });
      func.push(portEditorConfig(data, editorConfigPath));
    } else {
      func.push(
        writeStdout(hostMsg(`Failed to handle ${editorConfigPath}.`, "warn")),
        writeStdout({[EDITOR_CONFIG_RES]: null})
      );
    }
    return Promise.all(func);
  };

  /**
   * view local file
   * @param {string} uri - local file uri
   * @returns {?AsyncFunction} - spawn child process
   */
  const viewLocalFile = async uri => {
    let func;
    if (await isString(uri)) {
      const {protocol} = new URL(uri);
      if (protocol === "file:") {
        const file = await convertUriToFilePath(uri);
        if (file && isFile(file)) {
          func = spawnChildProcess(file);
        }
      }
    }
    return func || null;
  };

  /* handlers */
  /**
   * handle created temporary file
   * @param {Object} obj - temporary file data
   * @returns {Promise.<Array>} - results of each handler
   */
  const handleCreatedTmpFile = async (obj = {}) => {
    const {filePath} = obj;
    const func = [];
    if (await isFile(filePath)) {
      func.push(spawnChildProcess(filePath), portFileData(obj));
    }
    return Promise.all(func);
  };

  /**
   * handle message
   * @param {*} msg - message
   * @returns {Promise.<Array>} - results of each handler
   */
  const handleMsg = async msg => {
    const func = [];
    const items = msg && Object.keys(msg);
    if (items && items.length) {
      for (const item of items) {
        const obj = msg[item];
        switch (item) {
          case EDITOR_CONFIG_GET:
            func.push(getEditorConfig(obj));
            break;
          case LOCAL_FILE_VIEW:
            func.push(viewLocalFile(obj));
            break;
          case TMP_FILE_CREATE:
            func.push(createTmpFile(obj).then(handleCreatedTmpFile));
            break;
          case TMP_FILE_GET:
            func.push(getTmpFile(obj));
            break;
          case TMP_FILES_PB_REMOVE:
            func.push(initPrivateTmpDir(obj));
            break;
          default:
            func.push(
              writeStdout(hostMsg(`No handler found for ${item}.`, "warn"))
            );
        }
      }
    } else {
      func.push(writeStdout(hostMsg(`No handler found for ${msg}.`, "warn")));
    }
    return Promise.all(func);
  };

  /* input */
  const input = new Input();

  /**
   * read stdin
   * @param {string|Buffer} chunk - chunk
   * @returns {?Promise.<Array.<Promise>>} - composite a Promise chain
   */
  const readStdin = chunk => {
    const arr = input.decode(chunk);
    const func = [];
    Array.isArray(arr) && arr.length && arr.forEach(msg => {
      msg && func.push(handleMsg(msg));
    });
    return func.length && Promise.all(func).catch(handleReject) || null;
  };

  /* exit */
  /**
   * handle exit
   * @param {number} code - exit code
   * @returns {void}
   */
  const handleExit = code => {
    const msg = (new Output()).encode(hostMsg(`exit ${code || 0}`, "exit"));
    removeDir(path.join(...TMPDIR_APP), TMPDIR);
    msg && process.stdout.write(msg);
  };

  /* process */
  process.on("exit", handleExit);
  process.on("uncaughtException", throwErr);
  process.on("unhandleRejection", handleReject);
  process.stdin.on("data", readStdin);

  /* startup */
  Promise.all([
    createDir(TMPDIR_FILES, PERM_DIR),
    createDir(TMPDIR_FILES_PB, PERM_DIR),
  ]).then(portAppStatus).catch(handleReject);
}
<|endoftext|>


<commit_before>'use strict'

var async = require('async')
var moment = require('moment')
var parser = require('markdown-parse');
var tito = require('tito-api')

module.exports = GitEventsTito

function GitEventsTito(opts) {
  if (!(this instanceof GitEventsTito)) return new GitEventsTito(opts)
  this.t = tito({ authToken: opts.authToken, account: opts.account });
};

GitEventsTito.prototype.createEvent = function createEvent(payload, cb) {
  var that = this;

  async.waterfall([
    function(cb) { that.getLatestEvent(cb); },
    function(event, cb) { that.duplicateEvent(event, cb); },
    function(duplicatedEvent, cb) { that.updateEvent(payload, cb); }
  ], cb)
}

GitEventsTito.prototype.updateEvent = function updateEvent(payload, cb) {
  var updatedEvent;

  var titoUpdateEvent = function(err, eventDetails){
    this.t.updateEvent(eventDetails.slug, eventDetails)
      .on('data', function(data) { updatedEvent = data; })
      .on('end', function() { cb(null, updatedEvent); })
  }

  this.getEventDetails(payload, titoUpdateEvent.bind(this));
}

GitEventsTito.prototype.duplicateEvent = function duplicateEvent(event, cb) {
  var duplicatedEvent;
  this.t.duplicate(event.attributes.slug)
  .on('data', function(data) { duplicatedEvent = data; })
  .on('end', function() { cb(null, duplicatedEvent); })
}

GitEventsTito.prototype.getLatestEvent = function getLatestEvent(cb) {
  var events;
  this.t.events()
    .on('data', function (data) { events = data; })
    .on('end', function(){ cb(null, events[0]); })
}

GitEventsTito.prototype.issueIsValid = function issueIsValid(body) {
  if (!body.attributes) return false
  if (!body.attributes.name && !body.attributes.date && !body.attributes.venue && !body.attributes.address) return false
  return true
};

GitEventsTito.prototype.getEventSlug = function getEventSlug(date) {
  var m = moment(date.replace(/\//g, ' '), "DD MM YYYY");
  return m.format('MMMM').toLowerCase() + '-' + m.format('YYYY')
}

GitEventsTito.prototype.getEventDetails = function getEventDetails(payload, cb) {
  var that = this;
  parser(payload.issue.body, function(error, body) {
    if (error) { return new Error(error); }
    if (that.issueIsValid(body)) {
      var slug = that.getEventSlug(body.attributes.date)
      var startDate = moment(body.attributes.date.replace(/\//g, ' '), "DD MM YYYY").format();
      cb(null, {
        "data": {
          slug: slug,
          'start-date': startDate
        }
      })
    } else return new Error('invalid event info - body contains no attributes.');
  });
}
<commit_msg>refactor GitEventsTito<commit_after>'use strict'

var async = require('async')
var moment = require('moment')
var parser = require('markdown-parse');
var tito = require('tito-api')

module.exports = GitEventsTito

function GitEventsTito(opts) {
  if (!(this instanceof GitEventsTito)) return new GitEventsTito(opts)

  this.tito = tito({ authToken: opts.authToken, account: opts.account });
}

GitEventsTito.prototype.createEvent = function (payload, cb) {
  var self = this;

  async.waterfall([
    function(cb) { self.getLatestEvent(cb); },
    function(event, cb) { self.duplicateEvent(event, cb); },
    function(duplicatedEvent, cb) { self.updateEvent(payload, cb); }
  ], cb)
}

GitEventsTito.prototype.updateEvent = function (payload, cb) {
  var updatedEvent;

  var titoUpdateEvent = function(err, eventDetails){
    this.tito.updateEvent(eventDetails.slug, eventDetails)
      .on('data', function(data) { updatedEvent = data; })
      .on('end', function() { cb(null, updatedEvent); })
  }

  this.getEventDetails(payload, titoUpdateEvent.bind(this));
}

GitEventsTito.prototype.duplicateEvent = function (event, cb) {
  var duplicatedEvent;

  this.tito.duplicate(event.attributes.slug)
    .on('data', function(data) { duplicatedEvent = data; })
    .on('end', function() { cb(null, duplicatedEvent); })
}

GitEventsTito.prototype.getLatestEvent = function (cb) {
  var events;

  this.tito.events()
    .on('data', function (data) { events = data; })
    .on('end', function(){ cb(null, events[0]); })
}

GitEventsTito.prototype.issueIsValid = function (body) {
  if (!body.attributes) return false

  if (!body.attributes.name && !body.attributes.date && !body.attributes.venue && !body.attributes.address) return false

  return true
};

GitEventsTito.prototype.getEventSlug = function (date) {
  var m = moment(date.replace(/\//g, ' '), 'DD MM YYYY');

  return m.format('MMMM').toLowerCase() + '-' + m.format('YYYY')
}

GitEventsTito.prototype.getEventDetails = function (payload, cb) {
  var extractEventDetails = function(error, body) {
    if (error) return new Error(error);

    if (this.issueIsValid(body)) {
      var slug = this.getEventSlug(body.attributes.date)
      var startDate = moment(body.attributes.date.replace(/\//g, ' '), "DD MM YYYY").format();

      cb(null, {
        data: {
          slug: slug,
          'start-date': startDate
        }
      })
    }

    return new Error('invalid event info - body contains no attributes.');
  }

  parser(payload.issue.body, extractEventDetails.bind(this));
}
<|endoftext|>


<commit_before>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['react'], factory);
    } else if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require('react'), root);
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.React, root);
    }
}(this, function (React, global) {
    global = global || window
    var TOUCH = global.document && ( 'ontouchstart' in global.document || (global.document.navigator && global.document.navigator.msMaxTouchPoints) );
    var MOBILE_EVENTS = { down: 'onTouchStart', drag: 'onTouchMove', drop: 'onTouchEnd', move: 'touchmove', up: 'touchend' };
    var DESKTOP_EVENTS = { down: 'onMouseDown', drag: 'onDragOver', drop: 'onDrop', move: 'mousemove', up: 'mouseup' }
    var DEVICE_EVENTS = TOUCH ? MOBILE_EVENTS : DESKTOP_EVENTS;

    return React.createClass({
        propTypes: {
            scale: React.PropTypes.number,
            image: React.PropTypes.string,
            border: React.PropTypes.number,
            width: React.PropTypes.number,
            height: React.PropTypes.number,
            color: React.PropTypes.arrayOf(React.PropTypes.number),
            onImageReady: React.PropTypes.func,
        },

        getDefaultProps: function () {
            return {
                scale: 1,
                border: 25,
                width: 200,
                height: 200,
                color: [0, 0, 0, 0.5],
                onImageReady: function() {}
            }
        },

        getInitialState: function () {
            return {
                drag: false,
                my: null,
                mx: null,
                image: {
                    x: 0,
                    y: 0
                }
            };
        },

        getDimensions: function () {
            return {
                width: this.props.width,
                height: this.props.height,
                border: this.props.border,
                canvas: {
                    width: this.props.width + (this.props.border * 2),
                    height: this.props.height + (this.props.border * 2)
                }
            }
        },

        getImage: function (type, quality) {
            var dom = document.createElement('canvas');
            var context = dom.getContext('2d');
            var dimensions = this.getDimensions();

            dom.width = dimensions.width;
            dom.height = dimensions.height;

            context.globalCompositeOperation = 'destination-over';

            var imageState = this.state.image;

            this.paintImage(context, {
                resource: imageState.resource,
                x: imageState.x - dimensions.border,
                y: imageState.y - dimensions.border,
                width: imageState.width,
                height: imageState.height
            });

            return dom.toDataURL(type, quality);
        },

        isDataURL: function(str) {
            regex = /^\s*data:([a-z]+\/[a-z]+(;[a-z\-]+\=[a-z\-]+)?)?(;base64)?,[a-z0-9\!\$\&\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i;
            return !!str.match(regex);
        },

        loadImage: function (imageURL) {
            var imageObj = new Image();
            imageObj.onload = this.handleImageReady.bind(this, imageObj);
            if (!this.isDataURL(imageURL)) imageObj.crossOrigin = 'anonymous';
            imageObj.src = imageURL;
        },

        componentDidMount: function () {
            var context = this.getDOMNode().getContext('2d');
            if (this.props.image) {
                this.loadImage(this.props.image);
            }
            this.paint(context);
            document && document.addEventListener('mousemove', this.handleMouseMove, false);
            document && document.addEventListener('mouseup', this.handleMouseUp, false);
        },

        componentWillUnmount: function () {
            document && document.removeEventListener('mousemove', this.handleMouseMove, false);
            document && document.removeEventListener('mouseup', this.handleMouseUp, false);
        },

        componentDidUpdate: function () {
            var context = this.getDOMNode().getContext('2d');
            context.clearRect(0, 0, this.getDimensions().canvas.width, this.getDimensions().canvas.height);
            this.paint(context);
            this.paintImage(context, this.state.image);
        },

        handleImageReady: function (image) {
            var imageState = this.getInitialSize(image.width, image.height);
            imageState.resource = image;
            imageState.x = this.props.border;
            imageState.y = this.props.border;
            this.setState({drag: false, image: imageState}, this.props.onImageReady);
        },

        getInitialSize: function (width, height) {
            var newHeight, newWidth, dimensions, canvasRatio, imageRatio;

            dimensions = this.getDimensions();

            canvasRatio = dimensions.height / dimensions.width;
            imageRatio = height / width;

            if (canvasRatio > imageRatio) {
                newHeight = (this.getDimensions().height);
                newWidth = (width * (newHeight / height));
            } else {
                newWidth = (this.getDimensions().width);
                newHeight = (height * (newWidth / width));
            }

            return {
                height: newHeight,
                width: newWidth
            };
        },

        componentWillReceiveProps: function (newProps) {
            var image = this.state.image;

            if (this.props.image != newProps.image) {
                this.loadImage(newProps.image);
            }
        },

        paintImage: function (context, image) {
            if (image.resource) {
                var position = this.calculatePosition(image);
                context.save();
                context.globalCompositeOperation = 'destination-over';
                context.drawImage(image.resource, image.x, image.y, position.width, position.height);
                context.restore();
            }
        },

        calculatePosition: function (image) {
            image = image || this.state.image;
            var x, y, width, height, dimensions = this.getDimensions();

            width = image.width * this.props.scale;
            height = image.height * this.props.scale;
            var widthDiff = (width - image.width) / 2;
            var heightDiff = (height - image.height) / 2;
            x = image.x - widthDiff;
            y = image.y - heightDiff;

            // top and left border bounding
            x = Math.min(x, dimensions.border);
            y = Math.min(y, dimensions.border);

            // right and bottom
            var fromBottom = height + (y - dimensions.border);
            y = fromBottom > dimensions.height ? y : (y + (dimensions.height - fromBottom));
            var fromRight = width + (x - dimensions.border);
            x = fromRight > dimensions.width ? x : (x + (dimensions.width - fromRight));

            return {
                x: x,
                y: y,
                height: height,
                width: width
            }
        },

        paint: function (context) {
            context.save();
            context.translate(0, 0);
            context.fillStyle = "rgba("+this.props.color.slice(0, 4).join(",")+")";

            var dimensions = this.getDimensions();

            var borderSize = dimensions.border;
            var height = dimensions.canvas.height;
            var width = dimensions.canvas.width;

            context.fillRect(0, 0, width, borderSize); // top
            context.fillRect(0, height - borderSize, width, borderSize); // bottom
            context.fillRect(0, borderSize, borderSize, height - (borderSize * 2)); // left
            context.fillRect(width - borderSize, borderSize, borderSize, height - (borderSize * 2)); // right

            context.restore();
        },

        handleMouseDown: function () {
            this.setState({
                drag: true,
                mx: null,
                my: null
            });
        },
        handleMouseUp: function () {
            if (this.state.drag) {
                this.setState({drag: false});
            }
        },

        handleMouseMove: function (e) {
            if (false == this.state.drag) {
                return;
            }

            var newState = {}
            var dimensions = this.getDimensions();
            var imageState = this.state.image;
            var lastX = imageState.x;
            var lastY = imageState.y;

            var mousePositionX = TOUCH ? event.targetTouches[0].pageX : e.clientX;
            var mousePositionY = TOUCH ? event.targetTouches[0].pageY : e.clientY;

            newState = { mx: mousePositionX, my: mousePositionY, image: imageState };

            if (this.state.mx && this.state.my) {
                var xDiff = this.state.mx - mousePositionX;
                var yDiff = this.state.my - mousePositionY;

                imageState.y = this.getBoundedY(lastY - yDiff);
                imageState.x = this.getBoundedX(lastX - xDiff);
            }

            this.setState(newState);
        },

        getBoundedX: function (x) {
            var image = this.state.image;
            var dimensions = this.getDimensions();
            var scale = this.props.scale;
            var widthDiff = Math.ceil((image.width * scale - image.width) / 2);
            var rightPoint = Math.floor(-image.width*scale + dimensions.width + dimensions.border);
            var leftPoint = dimensions.border;

            var result;
            if (x - widthDiff >= dimensions.border) result = dimensions.border + widthDiff;
            if (x < rightPoint) result = rightPoint;
            if (x > leftPoint) result = leftPoint;

            return result || x;
        },

        getBoundedY: function (y) {
            var image = this.state.image;
            var dimensions = this.getDimensions();
            var scale = this.props.scale;
            var heightDiff = Math.ceil((image.height * scale - image.height) / 2);
            var bottomPoint = Math.ceil((-image.height * scale + dimensions.height + dimensions.border));
            var topPoint = dimensions.border;

            var result;
            if (y - heightDiff >= dimensions.border) result = dimensions.border + heightDiff;
            if (y < bottomPoint) result = bottomPoint;
            if (y > topPoint) result = topPoint;

            return result || y;
        },

        handleDragOver: function (e) {
            e.preventDefault();
        },

        handleDrop: function (e) {
            e.stopPropagation();
            e.preventDefault();

            var reader = new FileReader();
            reader.onload = this.handleUploadReady;
            reader.readAsDataURL(e.dataTransfer.files[0]);
        },

        handleUploadReady: function (e) {
            this.loadImage(e.target.result);
        },

        render: function () {
            var attributes = {
                width: this.getDimensions().canvas.width,
                height: this.getDimensions().canvas.height,
            }
            attributes[DESKTOP_EVENTS['down']] =  this.handleMouseDown;
            attributes[DESKTOP_EVENTS['drag']] =  this.handleDragOver;
            attributes[DESKTOP_EVENTS['drop']] =  this.handleDrop;
            if(TOUCH){
                attributes[MOBILE_EVENTS['down']] =  this.handleMouseDown;
                attributes[MOBILE_EVENTS['drag']] =  this.handleDragOver;
                attributes[MOBILE_EVENTS['drop']] =  this.handleDrop;
            }
            return React.createElement('canvas', attributes, null);
        }

    });

}));
<commit_msg>expose as AvatarEditor global to match name used in examples<commit_after>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['react'], factory);
    } else if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require('react'), root);
    } else {
        // Browser globals (root is window)
        root.AvatarEditor = factory(root.React, root);
    }
}(this, function (React, global) {
    global = global || window
    var TOUCH = global.document && ( 'ontouchstart' in global.document || (global.document.navigator && global.document.navigator.msMaxTouchPoints) );
    var MOBILE_EVENTS = { down: 'onTouchStart', drag: 'onTouchMove', drop: 'onTouchEnd', move: 'touchmove', up: 'touchend' };
    var DESKTOP_EVENTS = { down: 'onMouseDown', drag: 'onDragOver', drop: 'onDrop', move: 'mousemove', up: 'mouseup' }
    var DEVICE_EVENTS = TOUCH ? MOBILE_EVENTS : DESKTOP_EVENTS;

    return React.createClass({
        propTypes: {
            scale: React.PropTypes.number,
            image: React.PropTypes.string,
            border: React.PropTypes.number,
            width: React.PropTypes.number,
            height: React.PropTypes.number,
            color: React.PropTypes.arrayOf(React.PropTypes.number),
            onImageReady: React.PropTypes.func,
        },

        getDefaultProps: function () {
            return {
                scale: 1,
                border: 25,
                width: 200,
                height: 200,
                color: [0, 0, 0, 0.5],
                onImageReady: function() {}
            }
        },

        getInitialState: function () {
            return {
                drag: false,
                my: null,
                mx: null,
                image: {
                    x: 0,
                    y: 0
                }
            };
        },

        getDimensions: function () {
            return {
                width: this.props.width,
                height: this.props.height,
                border: this.props.border,
                canvas: {
                    width: this.props.width + (this.props.border * 2),
                    height: this.props.height + (this.props.border * 2)
                }
            }
        },

        getImage: function (type, quality) {
            var dom = document.createElement('canvas');
            var context = dom.getContext('2d');
            var dimensions = this.getDimensions();

            dom.width = dimensions.width;
            dom.height = dimensions.height;

            context.globalCompositeOperation = 'destination-over';

            var imageState = this.state.image;

            this.paintImage(context, {
                resource: imageState.resource,
                x: imageState.x - dimensions.border,
                y: imageState.y - dimensions.border,
                width: imageState.width,
                height: imageState.height
            });

            return dom.toDataURL(type, quality);
        },

        isDataURL: function(str) {
            regex = /^\s*data:([a-z]+\/[a-z]+(;[a-z\-]+\=[a-z\-]+)?)?(;base64)?,[a-z0-9\!\$\&\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i;
            return !!str.match(regex);
        },

        loadImage: function (imageURL) {
            var imageObj = new Image();
            imageObj.onload = this.handleImageReady.bind(this, imageObj);
            if (!this.isDataURL(imageURL)) imageObj.crossOrigin = 'anonymous';
            imageObj.src = imageURL;
        },

        componentDidMount: function () {
            var context = this.getDOMNode().getContext('2d');
            if (this.props.image) {
                this.loadImage(this.props.image);
            }
            this.paint(context);
            document && document.addEventListener('mousemove', this.handleMouseMove, false);
            document && document.addEventListener('mouseup', this.handleMouseUp, false);
        },

        componentWillUnmount: function () {
            document && document.removeEventListener('mousemove', this.handleMouseMove, false);
            document && document.removeEventListener('mouseup', this.handleMouseUp, false);
        },

        componentDidUpdate: function () {
            var context = this.getDOMNode().getContext('2d');
            context.clearRect(0, 0, this.getDimensions().canvas.width, this.getDimensions().canvas.height);
            this.paint(context);
            this.paintImage(context, this.state.image);
        },

        handleImageReady: function (image) {
            var imageState = this.getInitialSize(image.width, image.height);
            imageState.resource = image;
            imageState.x = this.props.border;
            imageState.y = this.props.border;
            this.setState({drag: false, image: imageState}, this.props.onImageReady);
        },

        getInitialSize: function (width, height) {
            var newHeight, newWidth, dimensions, canvasRatio, imageRatio;

            dimensions = this.getDimensions();

            canvasRatio = dimensions.height / dimensions.width;
            imageRatio = height / width;

            if (canvasRatio > imageRatio) {
                newHeight = (this.getDimensions().height);
                newWidth = (width * (newHeight / height));
            } else {
                newWidth = (this.getDimensions().width);
                newHeight = (height * (newWidth / width));
            }

            return {
                height: newHeight,
                width: newWidth
            };
        },

        componentWillReceiveProps: function (newProps) {
            var image = this.state.image;

            if (this.props.image != newProps.image) {
                this.loadImage(newProps.image);
            }
        },

        paintImage: function (context, image) {
            if (image.resource) {
                var position = this.calculatePosition(image);
                context.save();
                context.globalCompositeOperation = 'destination-over';
                context.drawImage(image.resource, image.x, image.y, position.width, position.height);
                context.restore();
            }
        },

        calculatePosition: function (image) {
            image = image || this.state.image;
            var x, y, width, height, dimensions = this.getDimensions();

            width = image.width * this.props.scale;
            height = image.height * this.props.scale;
            var widthDiff = (width - image.width) / 2;
            var heightDiff = (height - image.height) / 2;
            x = image.x - widthDiff;
            y = image.y - heightDiff;

            // top and left border bounding
            x = Math.min(x, dimensions.border);
            y = Math.min(y, dimensions.border);

            // right and bottom
            var fromBottom = height + (y - dimensions.border);
            y = fromBottom > dimensions.height ? y : (y + (dimensions.height - fromBottom));
            var fromRight = width + (x - dimensions.border);
            x = fromRight > dimensions.width ? x : (x + (dimensions.width - fromRight));

            return {
                x: x,
                y: y,
                height: height,
                width: width
            }
        },

        paint: function (context) {
            context.save();
            context.translate(0, 0);
            context.fillStyle = "rgba("+this.props.color.slice(0, 4).join(",")+")";

            var dimensions = this.getDimensions();

            var borderSize = dimensions.border;
            var height = dimensions.canvas.height;
            var width = dimensions.canvas.width;

            context.fillRect(0, 0, width, borderSize); // top
            context.fillRect(0, height - borderSize, width, borderSize); // bottom
            context.fillRect(0, borderSize, borderSize, height - (borderSize * 2)); // left
            context.fillRect(width - borderSize, borderSize, borderSize, height - (borderSize * 2)); // right

            context.restore();
        },

        handleMouseDown: function () {
            this.setState({
                drag: true,
                mx: null,
                my: null
            });
        },
        handleMouseUp: function () {
            if (this.state.drag) {
                this.setState({drag: false});
            }
        },

        handleMouseMove: function (e) {
            if (false == this.state.drag) {
                return;
            }

            var newState = {}
            var dimensions = this.getDimensions();
            var imageState = this.state.image;
            var lastX = imageState.x;
            var lastY = imageState.y;

            var mousePositionX = TOUCH ? event.targetTouches[0].pageX : e.clientX;
            var mousePositionY = TOUCH ? event.targetTouches[0].pageY : e.clientY;

            newState = { mx: mousePositionX, my: mousePositionY, image: imageState };

            if (this.state.mx && this.state.my) {
                var xDiff = this.state.mx - mousePositionX;
                var yDiff = this.state.my - mousePositionY;

                imageState.y = this.getBoundedY(lastY - yDiff);
                imageState.x = this.getBoundedX(lastX - xDiff);
            }

            this.setState(newState);
        },

        getBoundedX: function (x) {
            var image = this.state.image;
            var dimensions = this.getDimensions();
            var scale = this.props.scale;
            var widthDiff = Math.ceil((image.width * scale - image.width) / 2);
            var rightPoint = Math.floor(-image.width*scale + dimensions.width + dimensions.border);
            var leftPoint = dimensions.border;

            var result;
            if (x - widthDiff >= dimensions.border) result = dimensions.border + widthDiff;
            if (x < rightPoint) result = rightPoint;
            if (x > leftPoint) result = leftPoint;

            return result || x;
        },

        getBoundedY: function (y) {
            var image = this.state.image;
            var dimensions = this.getDimensions();
            var scale = this.props.scale;
            var heightDiff = Math.ceil((image.height * scale - image.height) / 2);
            var bottomPoint = Math.ceil((-image.height * scale + dimensions.height + dimensions.border));
            var topPoint = dimensions.border;

            var result;
            if (y - heightDiff >= dimensions.border) result = dimensions.border + heightDiff;
            if (y < bottomPoint) result = bottomPoint;
            if (y > topPoint) result = topPoint;

            return result || y;
        },

        handleDragOver: function (e) {
            e.preventDefault();
        },

        handleDrop: function (e) {
            e.stopPropagation();
            e.preventDefault();

            var reader = new FileReader();
            reader.onload = this.handleUploadReady;
            reader.readAsDataURL(e.dataTransfer.files[0]);
        },

        handleUploadReady: function (e) {
            this.loadImage(e.target.result);
        },

        render: function () {
            var attributes = {
                width: this.getDimensions().canvas.width,
                height: this.getDimensions().canvas.height,
            }
            attributes[DESKTOP_EVENTS['down']] =  this.handleMouseDown;
            attributes[DESKTOP_EVENTS['drag']] =  this.handleDragOver;
            attributes[DESKTOP_EVENTS['drop']] =  this.handleDrop;
            if(TOUCH){
                attributes[MOBILE_EVENTS['down']] =  this.handleMouseDown;
                attributes[MOBILE_EVENTS['drag']] =  this.handleDragOver;
                attributes[MOBILE_EVENTS['drop']] =  this.handleDrop;
            }
            return React.createElement('canvas', attributes, null);
        }

    });

}));
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var loaderUtils = require('loader-utils');
var chalk = require('chalk');

function errorFormat(msg) {
  return chalk.bold(chalk.red(msg));
};

function main(callback, loader, sourcePath) {
  fs.unlink('elm.js', function () {
    compileApp(callback, loader, sourcePath);
  });
}

function compileApp(callback, loader, sourcePath) {
  var make = spawn('elm-make', ['--output', 'elm.js', sourcePath], {stdio: [process.stdin, process.stdout, 'pipe']});
  var weErrored = false;
  var errors = '';

  make.stderr.on('data', function (data) {
    weErrored = true;
    errors += data;
  });

  make.on('error', function (err) {
    weErrored = true;
    errors += 'elm-make failed. do you have elm installed?';
  });

  make.on('close', function () {
    if (weErrored === false) {
      handleNormalClose(callback, loader);
    } else {
      console.log(errorFormat('\nelm-make compilation failed.'));
      console.log(errorFormat(errors));
      callback('elm-make errors in compilation');
    }
  });
}

function handleNormalClose(callback, loader) {
  fs.readFile('elm.js', function (err, data) {
    if (err) throw err;
    var output = '' + data + '\n' + 'module.exports = Elm;';
    callback(null, output);
  });
}

module.exports = function (source) {
  var callback = this.async();
  var sourcePath = loaderUtils.getRemainingRequest(this);

  this.cacheable();
  this.addDependency(sourcePath);

  if (!callback) {
    throw "can't handle non-async compilation. sorry.";
  }

  main(callback, this, sourcePath);
}
<commit_msg>remove CommonJS exporting of global Elm now that 0.17 bundles correctly<commit_after>var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var loaderUtils = require('loader-utils');
var chalk = require('chalk');

function errorFormat(msg) {
  return chalk.bold(chalk.red(msg));
};

function main(callback, loader, sourcePath) {
  fs.unlink('elm.js', function () {
    compileApp(callback, loader, sourcePath);
  });
}

function compileApp(callback, loader, sourcePath) {
  var make = spawn('elm-make', ['--output', 'elm.js', sourcePath], {stdio: [process.stdin, process.stdout, 'pipe']});
  var weErrored = false;
  var errors = '';

  make.stderr.on('data', function (data) {
    weErrored = true;
    errors += data;
  });

  make.on('error', function (err) {
    weErrored = true;
    errors += 'elm-make failed. do you have elm installed?';
  });

  make.on('close', function () {
    if (weErrored === false) {
      handleNormalClose(callback, loader);
    } else {
      console.log(errorFormat('\nelm-make compilation failed.'));
      console.log(errorFormat(errors));
      callback('elm-make errors in compilation');
    }
  });
}

function handleNormalClose(callback, loader) {
  fs.readFile('elm.js', function (err, data) {
    if (err) throw err;
    var output = '' + data;
    callback(null, output);
  });
}

module.exports = function (source) {
  var callback = this.async();
  var sourcePath = loaderUtils.getRemainingRequest(this);

  this.cacheable();
  this.addDependency(sourcePath);

  if (!callback) {
    throw "can't handle non-async compilation. sorry.";
  }

  main(callback, this, sourcePath);
}
<|endoftext|>


<commit_before>var spawn = require('child_process').spawn;
var moment = require('moment');
var knox = require('knox');
var fs = require('fs');

var credentials = require('./credentials');

var CMD = '/opt/vc/bin/raspistill';
var snapshotTime = process.env.delay || 10000; // in ms
var width = process.env.width || 640; // in pixels
var height = process.env.height || 480;

console.log('Taking snapshots every ' + snapshotTime + 'ms at ' + width + 'x' + height);

function removeLocalFile(filename) {
  fs.unlink(filename, function(err) {
    if (err) {
      console.log('Error removing file: ', err);
    } else {
      console.log('Removed local file: ', filename);
    }
  });
}

function uploadToS3(localPath, filename) {
  var client = knox.createClient(credentials);
  client.putFile(
    localPath + filename, filename,
    function(err, result) {
      if (err) {
        err = new Error('Upload Failure: ' + err);
      } else {
        removeLocalFile(localPath + filename);
      }
    }
  );
}

function snapPhoto() {
  var localPath = './images/';
  var filename = moment().format('MM-DD-YYYY_h:mm:ss') + '.jpg';
  var args = [
    '--output', localPath + filename,
    '--width', width,
    '--height', height
  ];

  var child_process = spawn(CMD, args);

  child_process.on('close', function () {
    console.log('Image written to file: ', filename);
    uploadToS3(localPath, filename);
    setTimeout(snapPhoto, snapshotTime);
  });
}

snapPhoto();
<commit_msg>Make s3 files public<commit_after>var spawn = require('child_process').spawn;
var moment = require('moment');
var knox = require('knox');
var fs = require('fs');

var credentials = require('./credentials');

var CMD = '/opt/vc/bin/raspistill';
var snapshotTime = process.env.delay || 10000; // in ms
var width = process.env.width || 640; // in pixels
var height = process.env.height || 480;

console.log('Taking snapshots every ' + snapshotTime + 'ms at ' + width + 'x' + height);

function removeLocalFile(filename) {
  fs.unlink(filename, function(err) {
    if (err) {
      console.log('Error removing file: ', err);
    } else {
      console.log('Removed local file: ', filename);
    }
  });
}

function uploadToS3(localPath, filename) {
  var client = knox.createClient(credentials);
  client.putFile(
    localPath + filename, filename, { 'x-amz-acl': 'public-read' },
    function(err, result) {
      if (err) {
        err = new Error('Upload Failure: ' + err);
      } else {
        removeLocalFile(localPath + filename);
      }
    }
  );
}

function snapPhoto() {
  var localPath = './images/';
  var filename = moment().format('MM-DD-YYYY_h:mm:ss') + '.jpg';
  var args = [
    '--output', localPath + filename,
    '--width', width,
    '--height', height
  ];

  var child_process = spawn(CMD, args);

  child_process.on('close', function () {
    console.log('Image written to file: ', filename);
    uploadToS3(localPath, filename);
    setTimeout(snapPhoto, snapshotTime);
  });
}

snapPhoto();
<|endoftext|>


<commit_before>// vimppm
// Copyright (c) 2013 CD01
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php

let INFO = xml`
    <plugin name="vimppm" version="0.0.2"
            href="https://github.com/cd01/vimppm"
            summary="Vimperator Plugin Manager"
            lang="en"
            xmlns="http://vimperator.org/namespaces/liberator">
        <author>CD01</author>
        <license>MIT</license>
        <project name="Vimperator" minVersion="3.7"/>

            Vimppm

        <item>
            <tags>:vimppm</tags>
            <spec>:vimppm</spec>
            <description>

                    manage plugin by vimppm

            </description>
        </item>

        <item>
            <tags>:vimppm install</tags>
            <spec>:vimppm install</spec>
            <description>

                    install all bundled plugins

            </description>
        </item>

        <item>
            <tags>:vimppm update</tags>
            <spec>:vimppm update</spec>
            <description>

                    update all bundled plugins

            </description>
        </item>
    </plugin>`;

var gitProtocol = (liberator.globalVariables.vimppm_default_git_protocol == undefined)
                ? 'https'
                : liberator.globalVariables.vimppm_default_git_protocol;
var vimppmDirPath = getVimppmDir();

function getVimppmDir() {
    var vimperatorDir = io.File(io.File.expandPath("~/.vimperator"));

    if (vimperatorDir.exists()) return "~/.vimperator/vimppm";

    vimperatorDir = io.File(io.File.expandPath("~/vimperator"));

    if (vimperatorDir.exists()) return "~/vimperator/vimppm";

    vimperatorDir = io.File(io.File.expandPath("~/_vimperator"));

    if (underscoreVimperatorDir.exists())
        return "~/_vimperator/vimppm";
    else
        return false;
}

function isGithubRepository(repositoryName) {
    return (repositoryName.indexOf('/') !== -1) ? true : false;
}

function isDirectory(path) {
    var pluginDir = io.File(io.File.expandPath(path));
    return (pluginDir.exists() && pluginDir.isDirectory()) ? true : false;
}

function installFromGithub(vimppmRepositoryName) {
    var pluginDirPath = vimppmDirPath + '/' + vimppmRepositoryName.split('/')[1];
    if (!isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            liberator.execute('!powershell -NoProfile -ExecutionPolicy unrestricted -Command cd "' + vimppmDirPath + '"; git clone ' + gitProtocol + '://github.com/' + vimppmRepositoryName + '.git');
        } else {
            liberator.execute('!cd ' + vimppmDirPath + ' && git clone ' + gitProtocol + '://github.com/' + vimppmRepositoryName + '.git');
        }
        return true;
    } else {
        liberator.echoerr(vimppmRepositoryName + ' is already exists!');
        return false;
    }
}

function gitPull(vimppmRepositoryName) {
    var pluginDirPath = vimppmDirPath + '/' + vimppmRepositoryName.split('/')[1];
    if (isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            liberator.execute('!powershell -NoProfile -ExecutionPolicy unrestricted -Command cd "' + pluginDirPath + '"; git pull');
        } else {
            liberator.execute('!cd ' + pluginDirPath + ' && git pull');
        }
        return true;
    } else {
        liberator.echoerr(vimppmRepositoryName + " isn't installed");
        return false;
    }
}

function installFromVimpr(pluginName) {
    var pluginDirPath = vimppmDirPath + '/' + pluginName;
    if (!isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            var downloadUrl = 'https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName;
            var destPath = io.File.expandPath(pluginDirPath + '/plugin/' + pluginName)
            liberator.execute('!powershell -NoProfile -ExecutionPolicy unrestricted -Command New-Item -type directory "' + io.File.expandPath(pluginDirPath) + '/plugin"');
            liberator.execute('!powershell -NoProfile -ExecutionPolicy unrestricted -Command $(new-object System.Net.WebClient).DownloadFile("' + downloadUrl + '", "' + destPath + '")');
        } else {
            liberator.execute('!mkdir -p ' + io.File.expandPath(pluginDirPath) + '/plugin');
            liberator.execute('!wget https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName + ' -P ' + io.File.expandPath(pluginDirPath) + '/plugin/');
        }
        return true;
    } else {
        liberator.echoerr(pluginName + ' is already exists!');
        return false;
    }
}

function updateFromVimpr(pluginName) {
    var pluginDirPath = vimppmDirPath + '/' + pluginName;
    if (isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            var downloadUrl = 'https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName;
            var destPath = io.File.expandPath(pluginDirPath + '/plugin/' + pluginName)
            liberator.execute('!powershell -NoProfile -ExecutionPolicy unrestricted -Command $(new-object System.Net.WebClient).DownloadFile("' + downloadUrl + '", "' + destPath + '")');
        } else {
            liberator.execute('!wget https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName + ' -O ' + io.File.expandPath(pluginDirPath) + '/plugin/' + pluginName);
        }
        return true;
    } else {
        liberator.echoerr(pluginName + " isn't installed");
        return false;
    }
}

(function () {
    var vimppmRepository = [];

    commands.addUserCommand(['vimppm'], 'VIMPeratorPluginManage command',
        function (args) {
            // vimppm "cd01/plugin-vimp" "{'hoge': 'hogehoge'}"
            // JSON.parse(args[1]).hoge;

            var repositoryName = args[0];
            if (isGithubRepository(repositoryName)) repositoryName = repositoryName.split('/')[1];
            var pluginDirPath = vimppmDirPath + '/' + repositoryName;

            if (isDirectory(pluginDirPath)) {
                liberator.execute('set rtp+=' + pluginDirPath);
                liberator.echo('Add ' + pluginDirPath + ' to runtimepath.');
            }

            vimppmRepository.push(args[0]);
        }, {
            subCommands: [
                new Command(
                    ['install'],
                    'install plugin',
                    function (args) {
                        if (args == "") {
                            for (var i = 0; i < vimppmRepository.length; i++) {
                                if (isGithubRepository(vimppmRepository[i]))
                                    installFromGithub(vimppmRepository[i]);
                                else
                                    installFromVimpr(vimppmRepository[i]);
                            }
                        } else {
                            if (isGithubRepository(args))
                                installFromGithub(args);
                            else
                                installFromVimpr(args);
                        }
                        liberator.echo("Vimperator plugins are installed!! Please, restart vimperator.");
                    }
                ),
                new Command(
                    ['update'],
                    'update plugin',
                    function (args) {
                        if (args == "") {
                            for (var i = 0; i < vimppmRepository.length; i++) {
                                if (isGithubRepository(vimppmRepository[i]))
                                    gitPull(vimppmRepository[i]);
                                else
                                    updateFromVimpr(vimppmRepository[i]);
                            }
                        } else {
                            if (isGithubRepository(args[0]))
                                gitPull(args[0]);
                            else
                                updateFromVimpr(args[0]);
                        }
                        liberator.echo("Vimperator plugins are updated. Please, restart vimperator.");
                    }
                )
            ]
        }
    );
})();

// vim:sw=4 ts=4 et :
<commit_msg>Add PowerShell window option<commit_after>// vimppm
// Copyright (c) 2013 CD01
// This software is released under the MIT License.
// http://opensource.org/licenses/mit-license.php

let INFO = xml`
    <plugin name="vimppm" version="0.0.2"
            href="https://github.com/cd01/vimppm"
            summary="Vimperator Plugin Manager"
            lang="en"
            xmlns="http://vimperator.org/namespaces/liberator">
        <author>CD01</author>
        <license>MIT</license>
        <project name="Vimperator" minVersion="3.7"/>

            Vimppm

        <item>
            <tags>:vimppm</tags>
            <spec>:vimppm</spec>
            <description>

                    manage plugin by vimppm

            </description>
        </item>

        <item>
            <tags>:vimppm install</tags>
            <spec>:vimppm install</spec>
            <description>

                    install all bundled plugins

            </description>
        </item>

        <item>
            <tags>:vimppm update</tags>
            <spec>:vimppm update</spec>
            <description>

                    update all bundled plugins

            </description>
        </item>
    </plugin>`;

var gitProtocol = (liberator.globalVariables.vimppm_default_git_protocol == undefined)
                ? 'https'
                : liberator.globalVariables.vimppm_default_git_protocol;
var vimppmDirPath = getVimppmDir();

function getVimppmDir() {
    var vimperatorDir = io.File(io.File.expandPath("~/.vimperator"));

    if (vimperatorDir.exists()) return "~/.vimperator/vimppm";

    vimperatorDir = io.File(io.File.expandPath("~/vimperator"));

    if (vimperatorDir.exists()) return "~/vimperator/vimppm";

    vimperatorDir = io.File(io.File.expandPath("~/_vimperator"));

    if (underscoreVimperatorDir.exists())
        return "~/_vimperator/vimppm";
    else
        return false;
}

function isGithubRepository(repositoryName) {
    return (repositoryName.indexOf('/') !== -1) ? true : false;
}

function isDirectory(path) {
    var pluginDir = io.File(io.File.expandPath(path));
    return (pluginDir.exists() && pluginDir.isDirectory()) ? true : false;
}

function installFromGithub(vimppmRepositoryName) {
    var pluginDirPath = vimppmDirPath + '/' + vimppmRepositoryName.split('/')[1];
    if (!isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            liberator.execute('!powershell -WindowStyle Minimized -NoProfile -ExecutionPolicy unrestricted -Command cd "' + vimppmDirPath + '"; git clone ' + gitProtocol + '://github.com/' + vimppmRepositoryName + '.git');
        } else {
            liberator.execute('!cd ' + vimppmDirPath + ' && git clone ' + gitProtocol + '://github.com/' + vimppmRepositoryName + '.git');
        }
        return true;
    } else {
        liberator.echoerr(vimppmRepositoryName + ' is already exists!');
        return false;
    }
}

function gitPull(vimppmRepositoryName) {
    var pluginDirPath = vimppmDirPath + '/' + vimppmRepositoryName.split('/')[1];
    if (isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            liberator.execute('!powershell -WindowStyle Minimized -NoProfile -ExecutionPolicy unrestricted -Command cd "' + pluginDirPath + '"; git pull');
        } else {
            liberator.execute('!cd ' + pluginDirPath + ' && git pull');
        }
        return true;
    } else {
        liberator.echoerr(vimppmRepositoryName + " isn't installed");
        return false;
    }
}

function installFromVimpr(pluginName) {
    var pluginDirPath = vimppmDirPath + '/' + pluginName;
    if (!isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            var downloadUrl = 'https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName;
            var destPath = io.File.expandPath(pluginDirPath + '/plugin/' + pluginName)
            liberator.execute('!powershell -WindowStyle Minimized -NoProfile -ExecutionPolicy unrestricted -Command New-Item -type directory "' + io.File.expandPath(pluginDirPath) + '/plugin"');
            liberator.execute('!powershell -WindowStyle Minimized -NoProfile -ExecutionPolicy unrestricted -Command $(new-object System.Net.WebClient).DownloadFile("' + downloadUrl + '", "' + destPath + '")');
        } else {
            liberator.execute('!mkdir -p ' + io.File.expandPath(pluginDirPath) + '/plugin');
            liberator.execute('!wget https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName + ' -P ' + io.File.expandPath(pluginDirPath) + '/plugin/');
        }
        return true;
    } else {
        liberator.echoerr(pluginName + ' is already exists!');
        return false;
    }
}

function updateFromVimpr(pluginName) {
    var pluginDirPath = vimppmDirPath + '/' + pluginName;
    if (isDirectory(pluginDirPath)) {
        if (liberator.has('Windows')) {
            var downloadUrl = 'https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName;
            var destPath = io.File.expandPath(pluginDirPath + '/plugin/' + pluginName)
            liberator.execute('!powershell -WindowStyle Minimized -NoProfile -ExecutionPolicy unrestricted -Command $(new-object System.Net.WebClient).DownloadFile("' + downloadUrl + '", "' + destPath + '")');
        } else {
            liberator.execute('!wget https://raw.github.com/vimpr/vimperator-plugins/master/' + pluginName + ' -O ' + io.File.expandPath(pluginDirPath) + '/plugin/' + pluginName);
        }
        return true;
    } else {
        liberator.echoerr(pluginName + " isn't installed");
        return false;
    }
}

(function () {
    var vimppmRepository = [];

    commands.addUserCommand(['vimppm'], 'VIMPeratorPluginManage command',
        function (args) {
            // vimppm "cd01/plugin-vimp" "{'hoge': 'hogehoge'}"
            // JSON.parse(args[1]).hoge;

            var repositoryName = args[0];
            if (isGithubRepository(repositoryName)) repositoryName = repositoryName.split('/')[1];
            var pluginDirPath = vimppmDirPath + '/' + repositoryName;

            if (isDirectory(pluginDirPath)) {
                liberator.execute('set rtp+=' + pluginDirPath);
                liberator.echo('Add ' + pluginDirPath + ' to runtimepath.');
            }

            vimppmRepository.push(args[0]);
        }, {
            subCommands: [
                new Command(
                    ['install'],
                    'install plugin',
                    function (args) {
                        if (args == "") {
                            for (var i = 0; i < vimppmRepository.length; i++) {
                                if (isGithubRepository(vimppmRepository[i]))
                                    installFromGithub(vimppmRepository[i]);
                                else
                                    installFromVimpr(vimppmRepository[i]);
                            }
                        } else {
                            if (isGithubRepository(args))
                                installFromGithub(args);
                            else
                                installFromVimpr(args);
                        }
                        liberator.echo("Vimperator plugins are installed!! Please, restart vimperator.");
                    }
                ),
                new Command(
                    ['update'],
                    'update plugin',
                    function (args) {
                        if (args == "") {
                            for (var i = 0; i < vimppmRepository.length; i++) {
                                if (isGithubRepository(vimppmRepository[i]))
                                    gitPull(vimppmRepository[i]);
                                else
                                    updateFromVimpr(vimppmRepository[i]);
                            }
                        } else {
                            if (isGithubRepository(args[0]))
                                gitPull(args[0]);
                            else
                                updateFromVimpr(args[0]);
                        }
                        liberator.echo("Vimperator plugins are updated. Please, restart vimperator.");
                    }
                )
            ]
        }
    );
})();

// vim:sw=4 ts=4 et :
<|endoftext|>