<commit_before>/**
 * Main JS file for GhostScroll behaviours
 */

var $post = $('.post');
var $first = $('.post.first');
var $last = $('.post.last');
var $fnav = $('.fixed-nav');
var $postholder = $('.post-holder');
var $postafter = $('.post-after');
var $sitehead = $('#site-head');

/* Globals jQuery, document */
(function ($) {
	"use strict";
	function srcTo (el) {
		$('html, body').animate({
			scrollTop: el.offset().top
		}, 1000);
	}
	$(document).ready(function(){

        // FitVids for responsive videos
        $('.post-content').fitVids();

		$postholder.each(function (e) {
			if(e % 2 != 0)
				$(this).addClass("odd");
		});

		$postafter.each(function (e) {
			var bg = $(this).parent().css('background-color')
			$(this).css('border-top-color', bg);

			if (e % 2 == 0) {
				$(this).addClass("even");
			}
		});

		$('.btn.first').click( function () {
			srcTo($first);
		});
		$('.btn.last').click( function () {
			srcTo($last);
		});
		$('#header-arrow').click(function () {
			srcTo($first);
		});
        $('#totop-arrow').click(function () {
            srcTo($sitehead);
        });

		$('.post-title').each(function () {
			var t = $(this).text();
			var index = $(this).parents('.post-holder').index();
			$fnav.append(""+t+"")
			$(this).parents('article').attr('id',t.toLowerCase().split(' ').join('-'));
			$('.fn-item').click(function () {
				var i = $(this).attr('item_index');
				var s = $(".post[item_index='"+i+"']");

				$('html, body').animate({
					scrollTop: s.offset().top
				}, 400);

			});
		});

		$('.post.last').next('.post-after').hide();
		if($sitehead.length) {
			$(window).scroll( function () {
				var w = $(window).scrollTop();
				var g = $sitehead.offset().top;
				var h = $sitehead.offset().top + $sitehead.height()-100;

				/*var paralex = 30 + w/13 + "%";
    			$sitehead.css("background-position-y", paralex); */

    			$sitehead.css("background-position-y");

				if(w >= g && w<=h) {
					$('.fixed-nav').fadeOut('fast');
				} else if($(window).width()>500) {
					$('.fixed-nav').fadeIn('fast');
				}

				$post.each(function () {
					var f = $(this).offset().top;
					var b = $(this).offset().top + $(this).height();
					var t = $(this).parent('.post-holder').index();
					var i = $(".fn-item[item_index='"+t+"']");
					var a = $(this).parent('.post-holder').prev('.post-holder').find('.post-after');

					$(this).attr('item_index', t);

					if(w >= f && w<=b) {
						i.addClass('active');
						a.fadeOut('slow');
					} else {
						i.removeClass('active');
						a.fadeIn('slow');
					}
				});
			});
		}

		$('ul li').before('');
		$('blockquote p').prepend('');
		$('blockquote p').append('');
	});

	$post.each(function () {
		var postText = $(this).html();
		var fa  = [];
		for(var i=0; i < icons.length; i++) {
			fa[i]       = {};
			fa[i].str   = "@"+ icons[i]+ "@";
			fa[i].icon  = icons[i];
			fa[i].int   = postText.search(fa[i].str);

			if(fa[i].int > -1 ) {
				fa[i].count = postText.match(new RegExp(fa[i].str,"g")).length;
				for(var j=0; j < fa[i].count; j++) {
					$(this).html($(this).html().replace(fa[i].str, ""))
				}
			}
		}
	});

}(jQuery));
<commit_msg>index js fix for performance<commit_after>/**
 * Main JS file for GhostScroll behaviours
 */

var $post = $('.post');
var $first = $('.post.first');
var $last = $('.post.last');
var $fnav = $('.fixed-nav');
var $postholder = $('.post-holder');
var $postafter = $('.post-after');
var $sitehead = $('#site-head');

/* Globals jQuery, document */
(function ($) {
	"use strict";
	function srcTo (el) {
		$('html, body').animate({
			scrollTop: el.offset().top
		}, 1000);
	}
	$(document).ready(function(){

        // FitVids for responsive videos
        $('.post-content').fitVids();

		$postholder.each(function (e) {
			if(e % 2 != 0)
				$(this).addClass("odd");
		});

		$postafter.each(function (e) {
			var bg = $(this).parent().css('background-color')
			$(this).css('border-top-color', bg);

			if (e % 2 == 0) {
				$(this).addClass("even");
			}
		});

		$('.btn.first').click( function () {
			srcTo($first);
		});
		$('.btn.last').click( function () {
			srcTo($last);
		});
		$('#header-arrow').click(function () {
			srcTo($first);
		});
        $('#totop-arrow').click(function () {
            srcTo($sitehead);
        });

		$('.post-title').each(function () {
			var t = $(this).text();
			var index = $(this).parents('.post-holder').index();
			$fnav.append(""+t+"")
			$(this).parents('article').attr('id',t.toLowerCase().split(' ').join('-'));
			$('.fn-item').click(function () {
				var i = $(this).attr('item_index');
				var s = $(".post[item_index='"+i+"']");

				$('html, body').animate({
					scrollTop: s.offset().top
				}, 100);

			});
		});

		$('.post.last').next('.post-after').hide();
		if($sitehead.length) {
			$(window).scroll( function () {
				var w = $(window).scrollTop();
				var g = $sitehead.offset().top;
				var h = $sitehead.offset().top + $sitehead.height()-100;

				/*var paralex = 30 + w/13 + "%";
    			$sitehead.css("background-position-y", paralex); */

    			$sitehead.css("background-position-y");

				if(w >= g && w<=h) {
					$('.fixed-nav').fadeOut('fast');
				} else if($(window).width()>500) {
					$('.fixed-nav').fadeIn('slow');
				}

				$post.each(function () {
					var f = $(this).offset().top;
					var b = $(this).offset().top + $(this).height();
					var t = $(this).parent('.post-holder').index();
					var i = $(".fn-item[item_index='"+t+"']");
					var a = $(this).parent('.post-holder').prev('.post-holder').find('.post-after');

					$(this).attr('item_index', t);

					if(w >= f && w<=b) {
						i.addClass('active');
						a.fadeOut('slow');
					} else {
						i.removeClass('active');
						a.fadeIn('slow');
					}
				});
			});
		}

		$('ul li').before('');
		$('blockquote p').prepend('');
		$('blockquote p').append('');
	});

	$post.each(function () {
		var postText = $(this).html();
		var fa  = [];
		for(var i=0; i < icons.length; i++) {
			fa[i]       = {};
			fa[i].str   = "@"+ icons[i]+ "@";
			fa[i].icon  = icons[i];
			fa[i].int   = postText.search(fa[i].str);

			if(fa[i].int > -1 ) {
				fa[i].count = postText.match(new RegExp(fa[i].str,"g")).length;
				for(var j=0; j < fa[i].count; j++) {
					$(this).html($(this).html().replace(fa[i].str, ""))
				}
			}
		}
	});

}(jQuery));
<|endoftext|>


<commit_before>/*jslint indent: 2 */
/*global document: false, MutationObserver: false, chrome: false*/
"use strict";

function $(s, elem) {
  elem = elem || document;
  return elem.querySelector(s);
}

function createTag(name, className, innerHTML) {
  var tag = document.createElement(name);
  tag.className = className;

  if (innerHTML) {
    tag.innerHTML = innerHTML;
  }

  return tag;
}

function createLink(className, tagName, linkHref) {
  var link;

  // Param defaults
  tagName  = tagName  || 'a';
  linkHref = linkHref || '#';
  link     = createTag(tagName, className);

  if (tagName === 'a') {
    link.href = '#';
  }

  link.appendChild(document.createTextNode('Start timer'));
  return link;
}

function invokeIfFunction(trial) {
  if (trial instanceof Function) {
    return trial();
  }
  return trial;
}

var togglbutton = {
  isStarted: false,
  render: function (selector, opts, renderer) {
    chrome.extension.sendMessage({type: 'activate'}, function (response) {
      if (response.success) {
        if (opts.observe) {
          var observer = new MutationObserver(function (mutations) {
            togglbutton.renderTo(selector, renderer);
          });
          observer.observe(document, {childList: true, subtree: true});
        } else {
          togglbutton.renderTo(selector, renderer);
        }
      }
    });
  },

  renderTo: function (selector, renderer) {
    var i, len, elems = document.querySelectorAll(selector);
    for (i = 0, len = elems.length; i < len; i += 1) {
      elems[i].classList.add('toggl');
    }
    for (i = 0, len = elems.length; i < len; i += 1) {
      renderer(elems[i]);
    }
  },

  createTimerLink: function (params) {
    var link = createLink('toggl-button');
    link.classList.add(params.className);

    if (params.buttonType === 'minimal') {
      link.classList.add('min');
      link.removeChild(link.firstChild);
    }

    link.addEventListener('click', function (e) {
      var opts, linkText, color = '';
      e.preventDefault();

      if (this.isStarted) {
        link.classList.remove('active');
        linkText = 'Start timer';
        opts = {type: 'stop'};
      } else {
        link.classList.add('active');
        color = '#1ab351';
        linkText = 'Stop timer';
        opts = {
          type: 'timeEntry',
          projectId: invokeIfFunction(params.projectId),
          description: invokeIfFunction(params.description),
          projectName: invokeIfFunction(params.projectName),
          createdWith: 'TogglButton - ' + params.className
        };
      }
      chrome.extension.sendMessage(opts);
      this.isStarted = !this.isStarted;
      link.style.color = color;
      if (params.buttonType !== 'minimal') {
        link.innerHTML = linkText;
      }
      return false;
    });

    // new button created - reset state
    this.isStarted = false;
    return link;
  }
};

function createOption(id, cid, clientName, projectName) {
  var text = '', option = document.createElement("option");
  option.setAttribute("value", id);
  option.setAttribute("data-client-id", cid);

  if (clientName) {
    text = clientName + ' - ';
  }
  option.text = text + projectName;

  if (projectName) {
    option.setAttribute("data-project-name", projectName);
  }
  if (clientName) {
    option.setAttribute("data-client-name", clientName);
  }

  return option;
}

function createProjectSelect(userData, className) {
  var clients, projectLabel, option, select = createTag('select', className);

  //add an empty (default) option
  select.appendChild(createOption("default", null, "Select a toggl project"));

  userData.projects.forEach(function (project) {
    clients = userData.clients.filter(function (elem, index, array) { return (elem.id === project.cid); });
    projectLabel = (clients.length > 0 ? clients[0].name + " - " : "") + project.name;
    select.appendChild(createOption(project.id, project.cid, projectLabel));
  });

  return select;
}
<commit_msg>Use unused var<commit_after>/*jslint indent: 2 */
/*global document: false, MutationObserver: false, chrome: false*/
"use strict";

function $(s, elem) {
  elem = elem || document;
  return elem.querySelector(s);
}

function createTag(name, className, innerHTML) {
  var tag = document.createElement(name);
  tag.className = className;

  if (innerHTML) {
    tag.innerHTML = innerHTML;
  }

  return tag;
}

function createLink(className, tagName, linkHref) {
  var link;

  // Param defaults
  tagName  = tagName  || 'a';
  linkHref = linkHref || '#';
  link     = createTag(tagName, className);

  if (tagName === 'a') {
    link.href = linkHref;
  }

  link.appendChild(document.createTextNode('Start timer'));
  return link;
}

function invokeIfFunction(trial) {
  if (trial instanceof Function) {
    return trial();
  }
  return trial;
}

var togglbutton = {
  isStarted: false,
  render: function (selector, opts, renderer) {
    chrome.extension.sendMessage({type: 'activate'}, function (response) {
      if (response.success) {
        if (opts.observe) {
          var observer = new MutationObserver(function (mutations) {
            togglbutton.renderTo(selector, renderer);
          });
          observer.observe(document, {childList: true, subtree: true});
        } else {
          togglbutton.renderTo(selector, renderer);
        }
      }
    });
  },

  renderTo: function (selector, renderer) {
    var i, len, elems = document.querySelectorAll(selector);
    for (i = 0, len = elems.length; i < len; i += 1) {
      elems[i].classList.add('toggl');
    }
    for (i = 0, len = elems.length; i < len; i += 1) {
      renderer(elems[i]);
    }
  },

  createTimerLink: function (params) {
    var link = createLink('toggl-button');
    link.classList.add(params.className);

    if (params.buttonType === 'minimal') {
      link.classList.add('min');
      link.removeChild(link.firstChild);
    }

    link.addEventListener('click', function (e) {
      var opts, linkText, color = '';
      e.preventDefault();

      if (this.isStarted) {
        link.classList.remove('active');
        linkText = 'Start timer';
        opts = {type: 'stop'};
      } else {
        link.classList.add('active');
        color = '#1ab351';
        linkText = 'Stop timer';
        opts = {
          type: 'timeEntry',
          projectId: invokeIfFunction(params.projectId),
          description: invokeIfFunction(params.description),
          projectName: invokeIfFunction(params.projectName),
          createdWith: 'TogglButton - ' + params.className
        };
      }
      chrome.extension.sendMessage(opts);
      this.isStarted = !this.isStarted;
      link.style.color = color;
      if (params.buttonType !== 'minimal') {
        link.innerHTML = linkText;
      }
      return false;
    });

    // new button created - reset state
    this.isStarted = false;
    return link;
  }
};

function createOption(id, cid, clientName, projectName) {
  var text = '', option = document.createElement("option");
  option.setAttribute("value", id);
  option.setAttribute("data-client-id", cid);

  if (clientName) {
    text = clientName + ' - ';
  }
  option.text = text + projectName;

  if (projectName) {
    option.setAttribute("data-project-name", projectName);
  }
  if (clientName) {
    option.setAttribute("data-client-name", clientName);
  }

  return option;
}

function createProjectSelect(userData, className) {
  var clients, projectLabel, option, select = createTag('select', className);

  //add an empty (default) option
  select.appendChild(createOption("default", null, "Select a toggl project"));

  userData.projects.forEach(function (project) {
    clients = userData.clients.filter(function (elem, index, array) { return (elem.id === project.cid); });
    projectLabel = (clients.length > 0 ? clients[0].name + " - " : "") + project.name;
    select.appendChild(createOption(project.id, project.cid, projectLabel));
  });

  return select;
}
<|endoftext|>


<commit_before>/**
 * Main JS file for Casper behaviours
 */

/*globals jQuery, document */
(function ($) {
    "use strict";

    $(document).ready(function(){

        $(".post-content").fitVids();

        // Calculates Reading Time
        $('.post-content').readingTime({
            readingTimeTarget: '.post-reading-time'
        });
    });

}(jQuery));
<commit_msg>make formal citations clickable<commit_after>/**
 * Main JS file for Casper behaviours
 */

/*globals jQuery, document */
(function ($) {
    "use strict";

    $(document).ready(function(){

        $(".post-content").fitVids();

        // Calculates Reading Time
        $('.post-content').readingTime({
            readingTimeTarget: '.post-reading-time'
        });

        $('span.citation').click(function(){
            $(location).attr('href', $(this).data("cites"));
        });
    });

}(jQuery));
<|endoftext|>


<commit_before>'use strict';

var Table = (function() {
  var eventObjects, $tableDiv, $tableBody, $footer, resultsVisilbe;

  function init() {
    $tableDiv = $('#overflowContent');
    $tableBody = $('#resultsTableBody');
    $footer = $('footer');
    resultsVisilbe = false;

    window.addEventListener('resize', setTablePosition);
    $('#content').on('resizestop', function() {
      setTablePosition();
    });
  }

  function setTablePosition() {
    let mapRect = document.getElementById('map').getBoundingClientRect();
    let mapHeight = mapRect.bottom - mapRect.top;
    let tableHeight = 0;
    if (resultsVisilbe) {
      $tableDiv.css('top', mapRect.bottom - mapRect.top + 'px');
      $tableDiv.css('visibility', 'hidden');
      $tableDiv.removeClass('isHidden');
      let tableRect = document.getElementById('overflowContent').getBoundingClientRect();
      tableHeight = tableRect.bottom - tableRect.top;
      $tableDiv.css('visibility', 'visible');
    }
    setFooterPosition(mapHeight, tableHeight);
  }

  function setFooterPosition(mapHeight = 0, tableHeight = 0) {
    let minTop = Math.max(window.innerHeight - 175, 667);
    let footerTop = Math.max(minTop, mapHeight + tableHeight);
    $footer.css('top', footerTop + 'px');
  }

  function hideTable() {
    $tableDiv.addClass('isHidden');
    resultsVisilbe = false;
  }

  function clearTableBody() {
    $tableBody.empty();
  }

  function createHTMLTable() {
    for (var i = 0; i < eventObjects.length; i++) {
      var eName = eventObjects[i].name;
      var eCity = eventObjects[i].venue.city;
      var eVenue = eventObjects[i].venue.name;
      var eDate = moment(eventObjects[i].startDate).format('dddd, MMM Do YYYY');

      $tableBody.append(
        '
' + eName + '	' + eVenue + '	' + eCity + '	' + eDate + '
'
      );
    }
    resultsVisilbe = true;
    setTablePosition();
  }

  function processEventResults(json) {
    console.log('tables got these results', json);

    var events = json._embedded.events;
    eventObjects = events.map(event => {
      return {
        name: event.name,
        startDate: event.dates.start.localDate,
        venue: {
          name: event._embedded.venues[0].name,
          city: event._embedded.venues[0].city.name
        }
      };
    });
    clearTableBody();
    createHTMLTable();
  }

  EVT.on('resultsValid', processEventResults);
  EVT.on('resetToInitialView', hideTable);
  EVT.on('resetToInitialView', setFooterPosition);
  EVT.on('init', init);
})();
<commit_msg>Correct footer positioning<commit_after>'use strict';

var Table = (function() {
  var eventObjects, $tableDiv, $tableBody, $footer, resultsVisilbe;

  function init() {
    $tableDiv = $('#overflowContent');
    $tableBody = $('#resultsTableBody');
    $footer = $('footer');
    resultsVisilbe = false;

    window.addEventListener('resize', setTablePosition);
    $('#content').on('resizestop', function() {
      setTablePosition();
    });
  }

  function setTablePosition() {
    let mapRect = document.getElementById('map').getBoundingClientRect();
    let mapHeight = mapRect.bottom - mapRect.top;
    let tableHeight = 0;
    if (resultsVisilbe) {
      $tableDiv.css('top', mapRect.bottom - mapRect.top + 'px');
      $tableDiv.css('visibility', 'hidden');
      $tableDiv.removeClass('isHidden');
      let tableRect = document.getElementById('overflowContent').getBoundingClientRect();
      tableHeight = tableRect.bottom - tableRect.top;
      $tableDiv.css('visibility', 'visible');
    }
    setFooterPosition(mapHeight, tableHeight);
  }

  function setFooterPosition(mapHeight = 0, tableHeight = 0) {
    let minTop = Math.max(window.innerHeight - 175, 628);
    let footerTop = Math.max(minTop, mapHeight + tableHeight);
    $footer.css('top', footerTop + 'px');
  }

  function hideTable() {
    $tableDiv.addClass('isHidden');
    resultsVisilbe = false;
  }

  function clearTableBody() {
    $tableBody.empty();
  }

  function createHTMLTable() {
    for (var i = 0; i < eventObjects.length; i++) {
      var eName = eventObjects[i].name;
      var eCity = eventObjects[i].venue.city;
      var eVenue = eventObjects[i].venue.name;
      var eDate = moment(eventObjects[i].startDate).format('dddd, MMM Do YYYY');

      $tableBody.append(
        '
' + eName + '	' + eVenue + '	' + eCity + '	' + eDate + '
'
      );
    }
    resultsVisilbe = true;
    setTablePosition();
  }

  function processEventResults(json) {
    console.log('tables got these results', json);

    var events = json._embedded.events;
    eventObjects = events.map(event => {
      return {
        name: event.name,
        startDate: event.dates.start.localDate,
        venue: {
          name: event._embedded.venues[0].name,
          city: event._embedded.venues[0].city.name
        }
      };
    });
    clearTableBody();
    createHTMLTable();
  }

  EVT.on('resultsValid', processEventResults);
  EVT.on('resetToInitialView', hideTable);
  EVT.on('resetToInitialView', setFooterPosition);
  EVT.on('init', init);
})();
<|endoftext|>


<commit_before>
$(function () {
  $('#vote, .votes').click(function() {
    var $this = $(this);
    var itemType = $this.attr('data-type');
    var itemId = $this.attr('data-id');

    var $symbol = $('#vote');  // button without the number of votes
    var $buttons = $(  // buttons to upvote the same item
      '.votes[data-id="' + itemId + '"][data-type="' + itemType + '"]'
    );

    // TODO: use django's url function
    var voteUrl = '/' + itemType + '/' + itemId +'/upvote';

    $.ajax({
      type: 'POST',
      url: voteUrl,
      data: 'csrfmiddlewaretoken=' + window.csrfToken
    }).always(function (xhr) {
      var result = $.parseJSON(xhr.responseText).result,
          curValue = parseInt($this.html(), 10),
          newValue, iconClasses, symbolIcon;

      // when clicking on button w/out n. of votes
      if (isNaN(curValue) && $buttons.length > 0) {
        curValue = parseInt($buttons.eq(0).html(), 10);
      }

      if (result === 'voted') {
        newValue = curValue + 1;
        iconClasses = 'lsf lsf2';
        symbolIcon = 'checkbox';
      }
      else if (result === 'unvoted') {
        newValue = curValue - 1;
        iconClasses = 'lsf';
        symbolIcon = 'check';
      }

      $symbol.html(symbolIcon);
      $buttons.html('' + newValue +' ');
    });
  });
}(jQuery));
<commit_msg>Corrected NaN bug on /link/upvotes/<commit_after>
$(function () {
  $('#vote, .votes').click(function() {
    var $this = $(this);
    var itemType = $this.attr('data-type');
    var itemId = $this.attr('data-id');

    var $symbol = $('#vote');  // button without the number of votes
    var $buttons = $(  // buttons to upvote the same item
      '.votes[data-id="' + itemId + '"][data-type="' + itemType + '"]'
    );

    // TODO: use django's url function
    var voteUrl = '/' + itemType + '/' + itemId +'/upvote';

    $.ajax({
      type: 'POST',
      url: voteUrl,
      data: 'csrfmiddlewaretoken=' + window.csrfToken
    }).always(function (xhr) {
      var result = $.parseJSON(xhr.responseText).result,
          curValue = parseInt($this.html(), 10),
          newValue, iconClasses, symbolIcon;

      // when clicking on button w/out n. of votes
      if (isNaN(curValue) && $buttons.length > 0) {
        curValue = parseInt($buttons.eq(0).html(), 10);
      }

      if (result === 'voted') {
        newValue = curValue + 1;
        iconClasses = 'lsf lsf2';
        symbolIcon = 'checkbox';
      }
      else if (result === 'unvoted') {
        newValue = curValue - 1;
        iconClasses = 'lsf';
        symbolIcon = 'check';
      }

      $symbol.html(symbolIcon);
      if (isNaN(newValue)) {
        newValue = '';
      }
      $buttons.html('' + newValue +' ');
    });
  });
}(jQuery));
<|endoftext|>


<commit_before>var chalk = require('chalk');
var shell = require('shelljs');

var isWin = !!process.platform.match(/^win/);
var pathSep = isWin ? ';' : ':';

var doctor = {
  errors: [],

  run: function () {
    this.checkNodePath();

    this.logErrors();
  },

  logErrors: function () {
    if (!this.errors.length) {
      console.log(chalk.green('[Yeoman Doctor] Everything looks alright!'));
      console.log();
      return;
    }
    console.log(chalk.red('[Yeoman Doctor] Uh oh, I found potential errors on your machine\n---------------\n'));
    this.errors.forEach(function (errMsg) {
      console.log('[' + chalk.red('Error') + '] ' + errMsg);
      console.log();
    });
  },

  checkNodePath: function () {
    if (!process.env.NODE_PATH) return;
    var nodePaths = process.env.NODE_PATH.split(pathSep);
    var npmRoot = shell.exec('npm -g root', { silent: true }).output.replace(/([\r\n])$/, '');
    if (nodePaths.indexOf(npmRoot) < 0) {
      this.nodePathMismatch({
        nodePaths: nodePaths,
        npmRoot: npmRoot
      });
    }
  },

  nodePathMismatch: function (val) {
    var output = '';
    output += 'NPM root value is not in your NODE_PATH\n';
    output += '  [' + chalk.cyan('info') + ']\n';
    output += [
      '    NODE_PATH = ' + val.nodePaths.join(pathSep),
      '    NPM root  = ' + val.npmRoot
    ].join('\n');
    output += '\n\n  [' + chalk.cyan('Fix') + '] Append the NPM root value to your NODE_PATH variable\n';

    if (!isWin) {
      output += [
        '    Add this line to your .bashrc',
        '      export NODE_PATH=$NODE_PATH:' + val.npmRoot,
        '    Or run this command',
        '      echo "export NODE_PATH=$NODE_PATH:' + val.npmRoot + '" >> ~/.bashrc && source ~/.bashrc'
      ].join('\n');
    }

    this.errors.push(output);
  }
};

doctor.run();
<commit_msg>Fix yo doctor for Windows user (Fix #130)<commit_after>var chalk = require('chalk');
var shell = require('shelljs');
var path = require('path');

var isWin = !!process.platform.match(/^win/);
var pathSep = isWin ? ';' : ':';

var doctor = {
  errors: [],

  run: function () {
    this.checkNodePath();

    this.logErrors();
  },

  logErrors: function () {
    if (!this.errors.length) {
      console.log(chalk.green('[Yeoman Doctor] Everything looks alright!'));
      console.log();
      return;
    }
    console.log(chalk.red('[Yeoman Doctor] Uh oh, I found potential errors on your machine\n---------------\n'));
    this.errors.forEach(function (errMsg) {
      console.log('[' + chalk.red('Error') + '] ' + errMsg);
      console.log();
    });
  },

  checkNodePath: function () {
    if (!process.env.NODE_PATH) return;
    var nodePaths = process.env.NODE_PATH.split(pathSep).map(path.normalize);
    var npmRoot = shell.exec('npm -g root', { silent: true }).output;
    npmRoot = path.normalize(npmRoot.trim());
    if (nodePaths.indexOf(npmRoot) < 0) {
      this.nodePathMismatch({
        nodePaths: nodePaths,
        npmRoot: npmRoot
      });
    }
  },

  nodePathMismatch: function (val) {
    var output = '';
    output += 'NPM root value is not in your NODE_PATH\n';
    output += '  [' + chalk.cyan('info') + ']\n';
    output += [
      '    NODE_PATH = ' + val.nodePaths.join(pathSep),
      '    NPM root  = ' + val.npmRoot
    ].join('\n');
    output += '\n\n  [' + chalk.cyan('Fix') + '] Append the NPM root value to your NODE_PATH variable\n';

    if (isWin) {
      output += [
        '    If you\'re using cmd.exe, run this command to fix the issue:',
        '      setx NODE_PATH "%NODE_PATH%;' + val.npmRoot + '"',
        '    Then restart your command line. Otherwise, you can setup NODE_PATH manually:',
        '      https://github.com/sindresorhus/guides/blob/master/set-environment-variables.md#windows'
      ].join('\n');
    } else {
      output += [
        '    Add this line to your .bashrc',
        '      export NODE_PATH=$NODE_PATH:' + val.npmRoot,
        '    Or run this command',
        '      echo "export NODE_PATH=$NODE_PATH:' + val.npmRoot + '" >> ~/.bashrc && source ~/.bashrc'
      ].join('\n');
    }

    this.errors.push(output);
  }
};

doctor.run();
<|endoftext|>


<commit_before>"use strict"
var LineMessaging = require('hubot-line-messaging-api')
var StickerMessage = require('hubot-line-messaging-api').StickerMessage
var PostbackMessage = require('hubot-line-messaging-api').PostbackMessage
var SendSticker = LineMessaging.SendSticker
var SendLocation = LineMessaging.SendLocation
var SendImage = LineMessaging.SendImage
var SendVideo = LineMessaging.SendVideo
var SendAudio = LineMessaging.SendAudio
var SendText = LineMessaging.SendText
var rss = require('../db/models/rss.js')
var users = require('../db/models/users.js')
var userSubscription = require('../db/models/userSubscription.js')
var category = require('../db/models/category.js')

// 3rd party libs
var imgur = require('imgur')
var Promise = require('bluebird')
var util = require('util')

// rss feed parser
var FeedParser = require('feedparser')
var request = require('request') // for fetching the feed

var FEED_LIMIT = 3
var DESCRIPTION_LENGTH = 60
var sendImageString = ""

var {
 SUBSCRIBE,
 UNSUBSCRIBE,
} = userSubscription

function uploadImages (res, respBody) {
  console.log('uploadImages---1')
  for(var index in respBody){
    var imgUrl = respBody[index].images
    if(index >= 0 && index <= 4)
    imgur.uploadUrl(imgUrl)
        .then(function (json) {
            var imgurUrl = json.data.link
            imgurUrl = imgurUrl.replace(/^http:\/\//i, 'https://')
            // image.push(new SendImage(imgurUrl, imgurUrl))
            // sendImageString = sendImageString + ", new SendImage('" + imgurUrl + "', '" + imgurUrl + "')"
            res.reply(new SendImage(imgurUrl, imgurUrl))
            console.log("?????", imgurUrl)
        })
        .catch(function (err) {
            console.error(err.message)
        })
  }
}

function pushImageByLine (res) {
  console.log('pushImageByLine---2')
  // eval("res.reply(sendImageString)")
}

function getRssFeeds (res, rssUrl, limit, offset) {
  // request rss link
  var req = request(rssUrl)
  var feedparser = new FeedParser()
  var feedNumber = 0
  var columns = []

  req.on('error', function (error) {
    // handle any request errors
  })

  req.on('response', function (res) {
    var stream = this // `this` is `req`, which is a stream

    if (res.statusCode !== 200) {
      this.emit('error', new Error('Bad status code'))
    }
    else {
      stream.pipe(feedparser)
    }
  })

  feedparser.on('error', function (error) {
    // always handle errors
  })

  feedparser.on('meta', function (meta) {
    console.log('===== %s =====', meta.title)
  })

  feedparser.on('readable', function () {
    // This is where the action is!
    var stream = this // `this` is `feedparser`, which is a stream
    var meta = this.meta // **NOTE** the "meta" is always available in the context of the feedparser instance
    var item

    while (item = stream.read()) {
      console.log('Got article: %s', item.title || item.description)

      var description = item.description
      var imgUrl = "https" + description.match(/:\/\/[^">]+/g)
      // remove html tag
      var clearDescription = description.replace(/<\/?[^>]+(>|$)/g, "")
      // substring by length
      if (clearDescription.length > DESCRIPTION_LENGTH) {
        var trimDescription = clearDescription.substring(0, DESCRIPTION_LENGTH - 3 ) + '...'
      } else {
        var trimDescription = clearDescription
      }

      var feedLink = item.link
      feedLink = feedLink.replace(/^http:\/\//i, 'https://')
      console.log('Got clearDescription: %s', trimDescription)

      var carousel = {
        "thumbnailImageUrl": imgUrl,
        "title": item.title,
        "text": trimDescription,
        "actions": [
          {
            "type": "uri",
            "label": "線上觀看",
            "uri": feedLink
          },
          {
            "type": "postback",
            "label": "訂閱",
            "data": "status=" + SUBSCRIBE + "&rssId=1"
          }
        ]
      }
      if (feedNumber > offset && feedNumber <= offset + limit) {
        columns.push(carousel)
      }

      if (feedNumber === offset + limit) {
        var obj = {
          "type": "template",
          "altText": "Engadget",
          "template": {
              "type": "carousel",
              "columns": columns
          }
        }
        // console.log('columns!!!!!', util.inspect(columns, false, null))
        res.reply(obj)
      }
      feedNumber++
    }
  })
}

const BuildTemplateMessage = LineMessaging.BuildTemplateMessage

const LINE_TOKEN = process.env.HUBOT_LINE_TOKEN

module.exports = function(robot){

  /**
   * Image URL (Max: 1000 characters)
   * HTTPS
   * JPEG or PNG
   * Aspect ratio: 1:1.51
   * Max width: 1024px
   * Max: 1 MB
   */

  /**
   * Filter all sticker message
   */
  var filterStickers = function(message){
    var result = false
    var stickerMsg = message.message
    if (stickerMsg && stickerMsg.type && stickerMsg.type === 'sticker'){
      result = true
    }
    var user = message.user
    robot.brain.set('USER:' + user.id, user)
    return result
  }

  /**
   * Filter all postback message
   */
  var filterPostback = function(message){
    var result = false
    var postbackMsg = message.message
    if (postbackMsg && postbackMsg.type && postbackMsg.type === 'postback'){
      result = true
      robot.http("https://api.line.me/v2/bot/profile/" + postbackMsg.user.id)
        .header('Authorization', "Bearer " + LINE_TOKEN)
        .get()(function(err, resp, body) {
          var respBody = JSON.parse(body)
          var entity = {id: respBody.userId, displayName: respBody.displayName}
          users.create(entity).then(function(result){
            console.log(respBody.userId + ' updated')
          })
        })
    }
    return result
  }

  /**
   * Do postback action
   */
  robot.listen(filterPostback, function(res){
    var postbackMsg = res.message.message.postback
    console.log(res.message.user.id + ", " + postbackMsg.data)
    var postbackData = postbackMsg.data.split('&')
    var entity = {userId: res.message.user.id}
    postbackData.forEach(function(param){
      var data = param.split('=')
      entity[data[0]] = data[1]
    })

    if (entity.status) {
      subscriptionRss(entity)
    }
    if (entity.categoryId) {
      // TODO show rss feed list
    }
  })

  /**
   * Reply any sticker message
   */
  robot.listen(filterStickers, function(res){
    var stickerMessage = res.message.message
    // This line is necessary to prevent error
    res.envelope.message = stickerMessage
    var sticker = new SendSticker(stickerMessage.stickerId, stickerMessage.packageId)
    res.reply(sticker)
  })

  /**
   * Get user profile
   */
  robot.hear(/whoami/i, function(res){
    robot.http("https://api.line.me/v2/bot/profile/" + res.message.user.id)
      .header('Authorization', "Bearer " + LINE_TOKEN)
      .get()(function(err, resp, body) {
        var respBody = JSON.parse(body)
        var text1 = new SendText('你好，' + respBody.displayName)
        var text2 = new SendText('使用者ID ' + res.message.user.id)
        res.reply(text1, text2)
      })
  })

  /**
   * Support on this bot
   */
  robot.hear(/help/i, function(res){
    var text1 = new SendText('輸入 [top]，顯示 Top 3 推薦類別')
    var text2 = new SendText('輸入 [list]，顯示訂閱清單')
    var text3 = new SendText('輸入 [whoami]，顯示個人資訊')
    res.reply(text1, text2, text3)
  })

  /**
   * Get Top 3 rss
   */
  robot.hear(/top/i, function(res){
    var categoryList = category.readAll().then(function(result){
      var msg = buildCarousel("category recommend", result)
      res.reply(msg)
    })
  })

  /**
   * List all rss subscription
   */
  robot.hear(/list/i, function(res){
    userSubscription.readByUserId(res.message.user.id).then(function(result){
      var msg = buildButton("subscription list", result)
      res.reply(msg)
    })
  })

  robot.hear(/rss/i, function(res){
    var rssUrl = 'http://feeds.feedburner.com/engadget/cstb'
    var limit = FEED_LIMIT
    var offset = 3
    getRssFeeds(res, rssUrl, limit, offset)
  })

  robot.hear(/a/i, function(res) {
    var btntemp = {
      "type": "template",
      "altText": "this is a buttons template",
      "template": {
          "type": "buttons",
          "thumbnailImageUrl": "https://example.com/bot/images/image.jpg",
          "title": "Menu",
          "text": "Please select",
          "actions": [
              {
                "type": "postback",
                "label": "Buy",
                "data": "action=buy&itemid=123"
              },
              {
                "type": "postback",
                "label": "Add to cart",
                "data": "action=add&itemid=123"
              },
              {
                "type": "uri",
                "label": "View detail",
                "uri": "http://example.com/page/123"
              }
          ]
      }
    }

    var carouselTemp = {
      "type": "template",
      "altText": "this is a carousel template",
      "template": {
          "type": "carousel",
          "columns": [
              {
                "thumbnailImageUrl": "https://example.com/bot/images/item1.jpg",
                "title": "this is menu",
                "text": "description",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Buy",
                        "data": "action=buy&itemid=111"
                    },
                    {
                        "type": "postback",
                        "label": "Add to cart",
                        "data": "action=add&itemid=111"
                    },
                    {
                        "type": "uri",
                        "label": "View detail",
                        "uri": "http://example.com/page/111"
                    }
                ]
              },
              {
                "thumbnailImageUrl": "https://example.com/bot/images/item2.jpg",
                "title": "this is menu",
                "text": "description",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Buy",
                        "data": "action=buy&itemid=222"
                    },
                    {
                        "type": "postback",
                        "label": "Add to cart",
                        "data": "action=add&itemid=222"
                    },
                    {
                        "type": "uri",
                        "label": "View detail",
                        "uri": "http://example.com/page/222"
                    }
                ]
              }
          ]
      }
    }
    res.reply(carouselTemp)
  })

  /**
   * push notification
   */
  robot.hear(/push/i, function(res){
    pushMessage('U33823165fc452e43a0a66ad60fba52bf', "通知")
    res.reply(new SendText('通知服務'))
  })

  /**
   * Push message API
   */
  function pushMessage(user, message) {
    var postData = JSON.stringify({
      "to": user,
      "messages":[
        {
          "type": "text",
          "text": message
        }
      ]
    })
    robot.http("https://api.line.me/v2/bot/message/push")
      .header('Authorization', "Bearer " + LINE_TOKEN)
      .header('Content-Type', 'application/json')
      .post(postData)(function(err, resp, body) {
        console.log(err, resp, body)
      })
  }

  /**
   * Build rss carousel
   */
  function buildCarousel(altText, result) {
    var columns = []
    result.rows.forEach(function(data){
      var carousel = {
        "thumbnailImageUrl": data.thumbnail,
        "title": data.name,
        "text": data.name,
        "actions": [
          {
            "type": "postback",
            "label": "顯示[" + data.name + "]",
            "data": "limit=3&offset=0&categoryId=" + data.id
          }
        ]
      }
      columns.push(carousel)
    })
    var obj = {
      "type": "template",
      "altText": altText,
      "template": {
          "type": "carousel",
          "columns": columns
      }
    }
    return obj
  }

  function buildButton(altText, result) {
    var actions = []
    result.rows.forEach(function(data){
      var action = {
        "type": "postback",
        "label": "取消訂閱[" + data.rssname + "]",
        "data": "status=" + UNSUBSCRIBE + "&rssId=" + data.id
      }
      actions.push(action)
    })
    var obj = {
      "type": "template",
      "altText": altText,
      "template": {
          "type": "buttons",
          "thumbnailImageUrl": "https://vignette4.wikia.nocookie.net/bladesandbeasts/images/8/84/Faerie_Dragon.png/revision/latest?cb=20121005191231",
          "title": "訂閱清單",
          "text": "點選取消訂閱",
          "actions": actions
      }
    }
    return obj
  }

  /**
   * Do subscribe
   */
  function subscriptionRss(entity) {
    console.log('subscriptionRss: ', entity)
    if (entity.status == SUBSCRIBE) {
      userSubscription.create(entity).then(function(result){
        rss.read(entity.rssId).then(function(rssResult){
          if (rssResult.rowCount > 0) {
            var rssResultData = rssResult.rows[0];
            pushMessage(entity.userId, "[" + rssResultData.rssname + "] 訂閱完成")
          }
        })
      }).catch(function(err){
        console.log(err)
      })
    } else if (entity.status = UNSUBSCRIBE) {
      userSubscription.update(entity).then(function(result){
        rss.read(entity.rssId).then(function(rssResult){
          if (rssResult.rowCount > 0) {
            var rssResultData = rssResult.rows[0];
            pushMessage(entity.userId, "[" + rssResultData.rssname + "] 已取消訂閱")
          }
        })
      }).catch(function(err){
        console.log(err)
      })
    }
  }
}
<commit_msg>add category function<commit_after>"use strict"
var LineMessaging = require('hubot-line-messaging-api')
var StickerMessage = require('hubot-line-messaging-api').StickerMessage
var PostbackMessage = require('hubot-line-messaging-api').PostbackMessage
var SendSticker = LineMessaging.SendSticker
var SendLocation = LineMessaging.SendLocation
var SendImage = LineMessaging.SendImage
var SendVideo = LineMessaging.SendVideo
var SendAudio = LineMessaging.SendAudio
var SendText = LineMessaging.SendText
var rss = require('../db/models/rss.js')
var users = require('../db/models/users.js')
var userSubscription = require('../db/models/userSubscription.js')
var category = require('../db/models/category.js')

// 3rd party libs
var imgur = require('imgur')
var Promise = require('bluebird')
var util = require('util')

// rss feed parser
var FeedParser = require('feedparser')
var request = require('request') // for fetching the feed

var FEED_LIMIT = 3
var DESCRIPTION_LENGTH = 60
var sendImageString = ""

var {
 SUBSCRIBE,
 UNSUBSCRIBE,
} = userSubscription

function uploadImages (res, respBody) {
  console.log('uploadImages---1')
  for(var index in respBody){
    var imgUrl = respBody[index].images
    if(index >= 0 && index <= 4)
    imgur.uploadUrl(imgUrl)
        .then(function (json) {
            var imgurUrl = json.data.link
            imgurUrl = imgurUrl.replace(/^http:\/\//i, 'https://')
            // image.push(new SendImage(imgurUrl, imgurUrl))
            // sendImageString = sendImageString + ", new SendImage('" + imgurUrl + "', '" + imgurUrl + "')"
            res.reply(new SendImage(imgurUrl, imgurUrl))
            console.log("?????", imgurUrl)
        })
        .catch(function (err) {
            console.error(err.message)
        })
  }
}

function pushImageByLine (res) {
  console.log('pushImageByLine---2')
  // eval("res.reply(sendImageString)")
}

function getRssLinks (res, entity) {
  rss.readByCategoryId(entity).then(function(result){
    var msg = buildCarouselByCategory("rss list", result)
    res.reply(msg)
  })
}

function getRssFeeds (res, rssUrl, limit, offset) {
  // request rss link
  var req = request(rssUrl)
  var feedparser = new FeedParser()
  var feedNumber = 0
  var columns = []

  req.on('error', function (error) {
    // handle any request errors
  })

  req.on('response', function (res) {
    var stream = this // `this` is `req`, which is a stream

    if (res.statusCode !== 200) {
      this.emit('error', new Error('Bad status code'))
    }
    else {
      stream.pipe(feedparser)
    }
  })

  feedparser.on('error', function (error) {
    // always handle errors
  })

  feedparser.on('meta', function (meta) {
    console.log('===== %s =====', meta.title)
  })

  feedparser.on('readable', function () {
    // This is where the action is!
    var stream = this // `this` is `feedparser`, which is a stream
    var meta = this.meta // **NOTE** the "meta" is always available in the context of the feedparser instance
    var item

    while (item = stream.read()) {
      console.log('Got article: %s', item.title || item.description)

      var description = item.description
      var imgUrl = "https" + description.match(/:\/\/[^">]+/g)
      // remove html tag
      var clearDescription = description.replace(/<\/?[^>]+(>|$)/g, "")
      // substring by length
      if (clearDescription.length > DESCRIPTION_LENGTH) {
        var trimDescription = clearDescription.substring(0, DESCRIPTION_LENGTH - 3 ) + '...'
      } else {
        var trimDescription = clearDescription
      }

      var feedLink = item.link
      feedLink = feedLink.replace(/^http:\/\//i, 'https://')
      console.log('Got clearDescription: %s', trimDescription)

      var carousel = {
        "thumbnailImageUrl": imgUrl,
        "title": item.title,
        "text": trimDescription,
        "actions": [
          {
            "type": "uri",
            "label": "線上觀看",
            "uri": feedLink
          },
          {
            "type": "postback",
            "label": "訂閱",
            "data": "status=" + SUBSCRIBE + "&rssId=1"
          }
        ]
      }
      if (feedNumber > offset && feedNumber <= offset + limit) {
        columns.push(carousel)
      }

      if (feedNumber === offset + limit) {
        var obj = {
          "type": "template",
          "altText": "Engadget",
          "template": {
              "type": "carousel",
              "columns": columns
          }
        }
        // console.log('columns!!!!!', util.inspect(columns, false, null))
        res.reply(obj)
      }
      feedNumber++
    }
  })
}

const BuildTemplateMessage = LineMessaging.BuildTemplateMessage

const LINE_TOKEN = process.env.HUBOT_LINE_TOKEN

module.exports = function(robot){

  /**
   * Image URL (Max: 1000 characters)
   * HTTPS
   * JPEG or PNG
   * Aspect ratio: 1:1.51
   * Max width: 1024px
   * Max: 1 MB
   */

  /**
   * Filter all sticker message
   */
  var filterStickers = function(message){
    var result = false
    var stickerMsg = message.message
    if (stickerMsg && stickerMsg.type && stickerMsg.type === 'sticker'){
      result = true
    }
    var user = message.user
    robot.brain.set('USER:' + user.id, user)
    return result
  }

  /**
   * Filter all postback message
   */
  var filterPostback = function(message){
    var result = false
    var postbackMsg = message.message
    if (postbackMsg && postbackMsg.type && postbackMsg.type === 'postback'){
      result = true
      robot.http("https://api.line.me/v2/bot/profile/" + postbackMsg.user.id)
        .header('Authorization', "Bearer " + LINE_TOKEN)
        .get()(function(err, resp, body) {
          var respBody = JSON.parse(body)
          var entity = {id: respBody.userId, displayName: respBody.displayName}
          users.create(entity).then(function(result){
            console.log(respBody.userId + ' updated')
          })
        })
    }
    return result
  }

  /**
   * Do postback action
   */
  robot.listen(filterPostback, function(res){
    var postbackMsg = res.message.message.postback
    console.log(res.message.user.id + ", " + postbackMsg.data)
    var postbackData = postbackMsg.data.split('&')
    var entity = {userId: res.message.user.id}
    postbackData.forEach(function(param){
      var data = param.split('=')
      entity[data[0]] = data[1]
    })

    if (entity.status) {
      subscriptionRss(entity)
    }
    if (entity.categoryId) {
      // TODO show rss feed list
      getRssLinks(res, entity);
    }
  })

  /**
   * Reply any sticker message
   */
  robot.listen(filterStickers, function(res){
    var stickerMessage = res.message.message
    // This line is necessary to prevent error
    res.envelope.message = stickerMessage
    var sticker = new SendSticker(stickerMessage.stickerId, stickerMessage.packageId)
    res.reply(sticker)
  })

  /**
   * Get user profile
   */
  robot.hear(/whoami/i, function(res){
    robot.http("https://api.line.me/v2/bot/profile/" + res.message.user.id)
      .header('Authorization', "Bearer " + LINE_TOKEN)
      .get()(function(err, resp, body) {
        var respBody = JSON.parse(body)
        var text1 = new SendText('你好，' + respBody.displayName)
        var text2 = new SendText('使用者ID ' + res.message.user.id)
        res.reply(text1, text2)
      })
  })

  /**
   * Support on this bot
   */
  robot.hear(/help/i, function(res){
    var text1 = new SendText('輸入 [top]，顯示 Top 3 推薦類別')
    var text2 = new SendText('輸入 [list]，顯示訂閱清單')
    var text3 = new SendText('輸入 [whoami]，顯示個人資訊')
    res.reply(text1, text2, text3)
  })

  /**
   * Get Top 3 rss
   */
  robot.hear(/top/i, function(res){
    var categoryList = category.readAll().then(function(result){
      var msg = buildCarousel("category recommend", result)
      res.reply(msg)
    })
  })

  /**
   * List all rss subscription
   */
  robot.hear(/list/i, function(res){
    userSubscription.readByUserId(res.message.user.id).then(function(result){
      var msg = buildButton("subscription list", result)
      res.reply(msg)
    })
  })

  robot.hear(/rss/i, function(res){
    var rssUrl = 'http://feeds.feedburner.com/engadget/cstb'
    var limit = FEED_LIMIT
    var offset = 3
    getRssFeeds(res, rssUrl, limit, offset)
  })

  robot.hear(/a/i, function(res) {
    var btntemp = {
      "type": "template",
      "altText": "this is a buttons template",
      "template": {
          "type": "buttons",
          "thumbnailImageUrl": "https://example.com/bot/images/image.jpg",
          "title": "Menu",
          "text": "Please select",
          "actions": [
              {
                "type": "postback",
                "label": "Buy",
                "data": "action=buy&itemid=123"
              },
              {
                "type": "postback",
                "label": "Add to cart",
                "data": "action=add&itemid=123"
              },
              {
                "type": "uri",
                "label": "View detail",
                "uri": "http://example.com/page/123"
              }
          ]
      }
    }

    var carouselTemp = {
      "type": "template",
      "altText": "this is a carousel template",
      "template": {
          "type": "carousel",
          "columns": [
              {
                "thumbnailImageUrl": "https://example.com/bot/images/item1.jpg",
                "title": "this is menu",
                "text": "description",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Buy",
                        "data": "action=buy&itemid=111"
                    },
                    {
                        "type": "postback",
                        "label": "Add to cart",
                        "data": "action=add&itemid=111"
                    },
                    {
                        "type": "uri",
                        "label": "View detail",
                        "uri": "http://example.com/page/111"
                    }
                ]
              },
              {
                "thumbnailImageUrl": "https://example.com/bot/images/item2.jpg",
                "title": "this is menu",
                "text": "description",
                "actions": [
                    {
                        "type": "postback",
                        "label": "Buy",
                        "data": "action=buy&itemid=222"
                    },
                    {
                        "type": "postback",
                        "label": "Add to cart",
                        "data": "action=add&itemid=222"
                    },
                    {
                        "type": "uri",
                        "label": "View detail",
                        "uri": "http://example.com/page/222"
                    }
                ]
              }
          ]
      }
    }
    res.reply(carouselTemp)
  })

  /**
   * push notification
   */
  robot.hear(/push/i, function(res){
    pushMessage('U33823165fc452e43a0a66ad60fba52bf', "通知")
    res.reply(new SendText('通知服務'))
  })

  /**
   * Push message API
   */
  function pushMessage(user, message) {
    var postData = JSON.stringify({
      "to": user,
      "messages":[
        {
          "type": "text",
          "text": message
        }
      ]
    })
    robot.http("https://api.line.me/v2/bot/message/push")
      .header('Authorization', "Bearer " + LINE_TOKEN)
      .header('Content-Type', 'application/json')
      .post(postData)(function(err, resp, body) {
        console.log(err, resp, body)
      })
  }

  /**
   * Build rss carousel
   */
  function buildCarousel(altText, result) {
    var columns = []
    result.rows.forEach(function(data){
      var carousel = {
        "thumbnailImageUrl": data.thumbnail,
        "title": data.name,
        "text": data.name,
        "actions": [
          {
            "type": "postback",
            "label": "顯示[" + data.name + "]",
            "data": "limit=3&offset=0&categoryId=" + data.id
          }
        ]
      }
      columns.push(carousel)
    })
    var obj = {
      "type": "template",
      "altText": altText,
      "template": {
          "type": "carousel",
          "columns": columns
      }
    }
    return obj
  }

  function buildCarouselByCategory (altText, result) {
    var columns = []
    result.rows.forEach(function(data){
      var carousel = {
        "thumbnailImageUrl": data.thumbnail,
        "title": data.rssname,
        "text": data.rssname,
        "actions": [
          {
            "type": "postback",
            "label": "顯示[" + data.rssname + "]",
            "data": "limit=3&offset=0&rssId=" + data.id
          }
        ]
      }
      columns.push(carousel)
    })
    var obj = {
      "type": "template",
      "altText": altText,
      "template": {
          "type": "carousel",
          "columns": columns
      }
    }
    return obj
  }

  function buildButton(altText, result) {
    var actions = []
    result.rows.forEach(function(data){
      var action = {
        "type": "postback",
        "label": "取消訂閱[" + data.rssname + "]",
        "data": "status=" + UNSUBSCRIBE + "&rssId=" + data.id
      }
      actions.push(action)
    })
    var obj = {
      "type": "template",
      "altText": altText,
      "template": {
          "type": "buttons",
          "thumbnailImageUrl": "https://vignette4.wikia.nocookie.net/bladesandbeasts/images/8/84/Faerie_Dragon.png/revision/latest?cb=20121005191231",
          "title": "訂閱清單",
          "text": "點選取消訂閱",
          "actions": actions
      }
    }
    return obj
  }

  /**
   * Do subscribe
   */
  function subscriptionRss(entity) {
    console.log('subscriptionRss: ', entity)
    if (entity.status == SUBSCRIBE) {
      userSubscription.create(entity).then(function(result){
        rss.read(entity.rssId).then(function(rssResult){
          if (rssResult.rowCount > 0) {
            var rssResultData = rssResult.rows[0];
            pushMessage(entity.userId, "[" + rssResultData.rssname + "] 訂閱完成")
          }
        })
      }).catch(function(err){
        console.log(err)
      })
    } else if (entity.status = UNSUBSCRIBE) {
      userSubscription.update(entity).then(function(result){
        rss.read(entity.rssId).then(function(rssResult){
          if (rssResult.rowCount > 0) {
            var rssResultData = rssResult.rows[0];
            pushMessage(entity.userId, "[" + rssResultData.rssname + "] 已取消訂閱")
          }
        })
      }).catch(function(err){
        console.log(err)
      })
    }
  }
}
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        vendor: [
            'classnames',
            'debug',
            'lodash',
            'react',
            'react-dom',
            'react-redux',
            'react-router',
            'react-router-dom',
            'react-waypoint',
            'redux',
            'redux-thunk',
        ],
    },
    output: {
        filename: 'js/[name].js',
        path: path.resolve(__dirname, '../build/client'),
        publicPath: '/',
    },
    resolve: {
        modules: [path.join(__dirname, '../src'), 'node_modules'],
        extensions: ['.js', '.jsx', '.json', '.scss'],
    },
    plugins: [
        new webpack.EnvironmentPlugin(['NODE_ENV']),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: 'js/vendor.bundle.js',
            minChunks: Infinity,
        }),
        new ExtractTextPlugin('css/[name].css'),
        new HtmlWebpackPlugin({
            title: 'React-Redux-Webpack-Boiler',
            template: path.resolve(__dirname, '../src/entrytemplate.ejs'),
        }),
    ],
    module: {
        rules: [
            {
                test: /\.(js|jsx|es6)?$/,
                include: [path.resolve(__dirname, '../src')],
                loader: 'babel-loader',
            },
            {
                test: /\.s?css$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                modules: true,
                                localIdentName:
                                    '[name]__[local]___[hash:base64:5]',
                            },
                        },
                        {
                            loader: 'postcss-loader',
                            options: { sourceMap: true },
                        },
                        'resolve-url-loader',
                        'sass-loader?sourceMap',
                    ],
                }),
            },
            {
                test: /\.(png|jpg|jpeg|gif|svg)$/,
                loader: 'url-loader',
                query: {
                    limit: 8192,
                    name: 'images/[name].[ext]?[hash]',
                },
            },
            {
                test: /\.(woff|woff2|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader',
                query: {
                    limit: 8192,
                    name: 'fonts/[name].[ext]?[hash]',
                },
            },
            {
                test: /\.(mp4|avi|mov)$/,
                loader: 'url-loader',
                query: {
                    limit: 10000,
                    name: 'videos/[name].[ext]?[hash]',
                },
            },
        ],
    },
};
<commit_msg>Add default for webpack EnvironmentPlugin to supress warnings<commit_after>const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        vendor: [
            'classnames',
            'debug',
            'lodash',
            'react',
            'react-dom',
            'react-redux',
            'react-router',
            'react-router-dom',
            'react-waypoint',
            'redux',
            'redux-thunk',
        ],
    },
    output: {
        filename: 'js/[name].js',
        path: path.resolve(__dirname, '../build/client'),
        publicPath: '/',
    },
    resolve: {
        modules: [path.join(__dirname, '../src'), 'node_modules'],
        extensions: ['.js', '.jsx', '.json', '.scss'],
    },
    plugins: [
        new webpack.EnvironmentPlugin({
            NODE_ENV: 'development',
        }),
        new webpack.optimize.ModuleConcatenationPlugin(),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: 'js/vendor.bundle.js',
            minChunks: Infinity,
        }),
        new ExtractTextPlugin('css/[name].css'),
        new HtmlWebpackPlugin({
            title: 'React-Redux-Webpack-Boiler',
            template: path.resolve(__dirname, '../src/entrytemplate.ejs'),
        }),
    ],
    module: {
        rules: [
            {
                test: /\.(js|jsx|es6)?$/,
                include: [path.resolve(__dirname, '../src')],
                loader: 'babel-loader',
            },
            {
                test: /\.s?css$/,
                use: ExtractTextPlugin.extract({
                    fallback: 'style-loader',
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                modules: true,
                                localIdentName:
                                    '[name]__[local]___[hash:base64:5]',
                            },
                        },
                        {
                            loader: 'postcss-loader',
                            options: { sourceMap: true },
                        },
                        'resolve-url-loader',
                        'sass-loader?sourceMap',
                    ],
                }),
            },
            {
                test: /\.(png|jpg|jpeg|gif|svg)$/,
                loader: 'url-loader',
                query: {
                    limit: 8192,
                    name: 'images/[name].[ext]?[hash]',
                },
            },
            {
                test: /\.(woff|woff2|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url-loader',
                query: {
                    limit: 8192,
                    name: 'fonts/[name].[ext]?[hash]',
                },
            },
            {
                test: /\.(mp4|avi|mov)$/,
                loader: 'url-loader',
                query: {
                    limit: 10000,
                    name: 'videos/[name].[ext]?[hash]',
                },
            },
        ],
    },
};
<|endoftext|>


<commit_before>var Heroku = require('heroku-client'),
	heroku = new Heroku({ token: process.env.HEROKU_API_KEY });

module.exports = function(robot){

	robot.respond(/list heroku apps/i, function(res){
		if (res.auth.isAdmin(res.message.user)){
			heroku.apps().list(function(err, apps){
				res.send(robot.util.formatJson(apps));
			});
		}
	});

	robot.respond(/get heroku info for (.*)/i, function(res){
		if (res.auth.isAdmin(res.message.user)){
			var app = heroku.apps(res.match[1]);
			res.send(robot.util.formatJson(app));
		}
	});

	robot.respond(/promote staging to production/i, function(res){
		if (res.auth.isAdmin(res.message.user)){
			heroku.post('/pipeline-promotions', {
				pipeline: {
					id: process.env.HEROKU_PIPELINE_ID
				},
				source: {
					app: {
						id: process.env.HEROKU_SOURCE_APP_ID
					}
				},
				targets: [
					{
						app: {
							id: process.env.HEROKU_TARGET_APP_ID
						}
					}
				]
			},
			function(err, app){
				if(!!err)
					res.reply('There was an error processing your request');
				else
					res.reply('Promotion initiated');
			});
		}
		else
			res.reply('Sorry, only admins can do that');
	});

}<commit_msg>Fix broken logic in heroku.js<commit_after>var Heroku = require('heroku-client'),
	heroku = new Heroku({ token: process.env.HEROKU_API_KEY });

module.exports = function(robot){

	robot.respond(/list heroku apps/i, function(res){
		if (res.auth.isAdmin(res.message.user)){
			heroku.apps().list(function(err, apps){
				res.send(robot.util.formatJson(apps));
			});
		}
	});

	robot.respond(/get heroku info for (.*)/i, function(res){
		if (res.auth.isAdmin(res.message.user)){
			var application = heroku.apps(res.match[1]);
			application.info(function(err, app){
				if (!!err)
					res.send(robot.util.formatJson(app));
			});
		}
	});

	robot.respond(/promote staging to production/i, function(res){
		if (res.auth.isAdmin(res.message.user)){
			heroku.post('/pipeline-promotions', {
				pipeline: {
					id: process.env.HEROKU_PIPELINE_ID
				},
				source: {
					app: {
						id: process.env.HEROKU_SOURCE_APP_ID
					}
				},
				targets: [
					{
						app: {
							id: process.env.HEROKU_TARGET_APP_ID
						}
					}
				]
			},
			function(err, app){
				if(!!err)
					res.reply('There was an error processing your request');
				else
					res.reply('Promotion initiated');
			});
		}
		else
			res.reply('Sorry, only admins can do that');
	});

}<|endoftext|>


<commit_before>var grunt = require('grunt');

module.exports = {
  feature: {
    command: [
      'read -p "Commit message: " msg',
      'FEATURE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"',
      'git checkout dev',
      'git merge --squash ${FEATURE_BRANCH} && git reset',
      'git add . && git commit -m "$msg"',
      'git branch -D ${FEATURE_BRANCH}'
    ].join('&&')
  },

  prepare: {
    command: 'git checkout -b release dev'
  },

  changelog: {
    command: [
      'touch CHANGELOG.md',
      'grunt conventionalChangelog',
      'git add CHANGELOG.md',
      'git commit -m "CHANGELOG"'
    ].join('&&')
  },

  prod: {
    command: [
      'git checkout prod',
      'git merge --no-ff staging -m "Release v<%= pkg.version %>"'
    ].join('&&')
  },

  dist: {
    command: [
      'grunt clean:all',
      'grunt build --target=prod',
      'git add "assets" "dist" "index.html" -f',
      'git commit -m "Distribution"'
    ].join('&&')
  },

  release: {
    command: [
      'git add . && git commit -m "v<%= pkg.version %>"',
      'git checkout -b prod origin/prod && git checkout -b staging prod',
      'git merge release',
      'grunt shell:changelog',
      'grunt shell:dist',
      'git checkout prod',
      'git merge --no-ff staging -m "Release v<%= pkg.version %>"',
      'grunt bump-commit',
      'git checkout dev',
      'git merge --no-ff release -m \'Merge branch "release" into "dev"\'',
      'git push',
      'git branch -D release && git branch -D staging && git branch -D prod',
      'grunt concurrent:review',
      'grunt build'
    ].join('&&')
  }
};<commit_msg>[SYS] Update shell.js<commit_after>var grunt = require('grunt');

module.exports = {
  feature: {
    command: [
      'read -p "Commit message: " msg',
      'FEATURE_BRANCH="$(git rev-parse --abbrev-ref HEAD)"',
      'git checkout dev',
      'git merge --squash ${FEATURE_BRANCH} && git reset',
      'git add . && git commit -m "$msg"',
      'git branch -D ${FEATURE_BRANCH}'
    ].join('&&')
  },

  prepare: {
    command: 'git checkout -b release dev'
  },

  changelog: {
    command: [
      'touch CHANGELOG.md',
      'grunt conventionalChangelog',
      'git add CHANGELOG.md',
      'git commit -m "CHANGELOG"'
    ].join('&&')
  },

  prod: {
    command: [
      'git checkout prod',
      'git merge --no-ff staging -m "Release v<%= pkg.version %>"'
    ].join('&&')
  },

  dist: {
    command: [
      'grunt clean:all',
      'grunt build --target=prod',
      'git add "assets" "dist" "index.html" -f',
      'git commit -m "Distribution"'
    ].join('&&')
  },

  release: {
    command: [
      'git add . && git commit -m "v<%= pkg.version %>"',
      'git checkout -b prod origin/prod && git checkout -b staging prod',
      'git merge --no-ff release -m \'Merge branch "release" into "staging"\'',
      'grunt shell:changelog',
      'grunt shell:dist',
      'git checkout prod',
      'git merge --no-ff staging -m "Release v<%= pkg.version %>"',
      'grunt bump-commit',
      'git checkout dev',
      'git merge --no-ff release -m \'Merge branch "release" into "dev"\'',
      'git push',
      'git branch -D release && git branch -D staging && git branch -D prod',
      'grunt concurrent:review',
      'grunt build'
    ].join('&&')
  }
};<|endoftext|>


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

var child_process = require('child_process')
  , path = require('path')
  , os = require('os')

var BIN = path.resolve(__dirname, '..', 'node_modules', '.bin', 'nodewebkit')

var lookup = {
    'darwin': osx_launch
  , 'linux': linux_launch
  , 'win32': win_launch
}

lookup[os.platform()]()

function win_launch() {
  spawn('node', [BIN])
}

function osx_launch() {
  spawn(BIN, [])
}

function linux_launch() {
  spawn('sudo', ['node', BIN])
}

function spawn() {
  var args = [].slice.call(arguments)

  child_process.spawn.apply(child_process, args.concat({stdio: 'inherit'}))
}
<commit_msg>fix windows compatability<commit_after>#!/usr/bin/env node

var child_process = require('child_process')
  , path = require('path')
  , os = require('os')

var BIN = path.resolve(
    __dirname
  , '..'
  , 'node_modules'
  , 'nodewebkit'
  , 'bin'
  , 'nodewebkit'
)

var lookup = {
    'darwin': osx_launch
  , 'linux': linux_launch
  , 'win32': win_launch
}

lookup[os.platform()]()

function win_launch() {
  spawn('node', [BIN])
}

function osx_launch() {
  spawn(BIN, [])
}

function linux_launch() {
  spawn('sudo', ['node', BIN])
}

function spawn() {
  var args = [].slice.call(arguments)

  child_process.spawn.apply(child_process, args.concat({stdio: 'inherit'}))
}
<|endoftext|>


<commit_before>(function() {
	'use strict';

	module.exports = {
		"lint": {
			"rules": {
				"html": {
					"gateway": {
						"doctype-first": true,
						"tag-pair": true,
						"tag-self-close": true,
						"id-unique": true,
						"attr-lowercase": true,
						"doctype-html5": true,
						"head-script-disabled": true
					},
					"templates": {
						"doctype-first": false,
						"tag-pair": true,
						"tag-self-close": true,
						"id-unique": true,
						"attr-lowercase": true,
						"doctype-html5": false,
						"head-script-disabled": true
					}
				},
				"css": {},
				"js": {
					"strict": true,
					"curly": true,
					"eqeqeq": true,
					"immed": true,
					"latedef": true,
					"newcap": true,
					"noarg": true,
					"sub": true,
					"undef": false,
					"boss": true,
					"eqnull": true,
					"browser": true,
					"unused": true,
					"proto": true,
					"expr": true,
					"globals": {
						"jQuery": true,
						"define": true,
						"require": true,
						"console": true,
						"$": true,
						"_": true,
						"asyncTest": true,
						"deepEqual": true,
						"equal": true,
						"expect": true,
						"module": true,
						"notDeepEqual": true,
						"notEqual": true,
						"notStrictEqual": true,
						"ok": true,
						"QUnit": true,
						"raises": true,
						"start": true,
						"stop": true,
						"strictEqual": true,
						"test": true,
						"throws": true,
						"prompt": true,
						"alert": true
					}
				},
				"jscs": {
					"disallowMultipleVarDecl": true,
					"disallowSpacesInsideObjectBrackets": true
				}
			}
		}
	};
})();<commit_msg>turn off jscs multi var def<commit_after>(function() {
	'use strict';

	module.exports = {
		"lint": {
			"rules": {
				"html": {
					"gateway": {
						"doctype-first": true,
						"tag-pair": true,
						"tag-self-close": true,
						"id-unique": true,
						"attr-lowercase": true,
						"doctype-html5": true,
						"head-script-disabled": true
					},
					"templates": {
						"doctype-first": false,
						"tag-pair": true,
						"tag-self-close": true,
						"id-unique": true,
						"attr-lowercase": true,
						"doctype-html5": false,
						"head-script-disabled": true
					}
				},
				"css": {},
				"js": {
					"strict": true,
					"curly": true,
					"eqeqeq": true,
					"immed": true,
					"latedef": true,
					"newcap": true,
					"noarg": true,
					"sub": true,
					"undef": false,
					"boss": true,
					"eqnull": true,
					"browser": true,
					"unused": true,
					"proto": true,
					"expr": true,
					"globals": {
						"jQuery": true,
						"define": true,
						"require": true,
						"console": true,
						"$": true,
						"_": true,
						"asyncTest": true,
						"deepEqual": true,
						"equal": true,
						"expect": true,
						"module": true,
						"notDeepEqual": true,
						"notEqual": true,
						"notStrictEqual": true,
						"ok": true,
						"QUnit": true,
						"raises": true,
						"start": true,
						"stop": true,
						"strictEqual": true,
						"test": true,
						"throws": true,
						"prompt": true,
						"alert": true
					}
				},
				"jscs": {
					"disallowMultipleVarDecl": false,
					"disallowSpacesInsideObjectBrackets": true
				}
			}
		}
	};
})();<|endoftext|>


<commit_before>'use strict';

const Broadcast = require('../../src/broadcast').Broadcast;
const Random    = require('../../src/random').Random;
const util = require('util');

exports.listeners = {

  playerEnter: l10n => {
    return (room, rooms, player, players, npc) => {
      const rand = Random.inRange(1, 5);
      if (rand === 3) {
        const itemDesc = item.getShortDesc();
        const msg = '<bold>The serpent uncoils, hissing.</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  playerDropItem: l10n  => {
    return (room, player, players, item) => {
      const rand = Random.inRange(1, 5);
      if (rand === 3) {
        const itemDesc = item.getShortDesc();
        const msg = '<bold>The python\'s tongue flickers over the ' + itemDesc + '</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  hit: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);
      const secondPartyMessage = Random.fromArray([
        'The roach\'s pincers nip your ' + hitLocation + '.',
        'The roach bites your ' + hitLocation + ', drawing a pinprick of blood.',
      ]);
      const thirdPartyMessage = Random.fromArray([
        'The roach\'s pincers nip ' + player.combat.getDesc() + '\'s ' + hitLocation + '.',
        'The roach bites ' + player.combat.getDesc() + ' in the ' + hitLocation + ' and a tiny pinprick of blood wells forth.',
      ]);
      toRoom({
        secondPartyMessage,
        thirdPartyMessage,
      });

    }
  },

  damaged: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);
      const secondPartyMessage = Random.fromArray([
        'The roach chitters as its antennae are bent at an odd angle.',
        'The roach\'s chitin splinters and cracks around its ' + hitLocation + '.',
        'The roach hisses as ichor oozes from its wounds.'
      ]);
      const thirdPartyMessage = Random.fromArray([
        'The roach chitters in pain as its ' + hitLocation + ' shatters.',
        'Hissing furiously, the roach rears its pincer-covered maw.',
        'Ichor oozes from the injured roach.'
      ]);
      toRoom({
          secondPartyMessage,
          thirdPartyMessage,
      });
    }
  },

};
<commit_msg>Add python hit script.<commit_after>'use strict';

const Broadcast = require('../../src/broadcast').Broadcast;
const Random    = require('../../src/random').Random;
const util = require('util');

exports.listeners = {

  playerEnter: l10n => {
    return (room, rooms, player, players, npc) => {
      const rand = Random.inRange(1, 5);
      if (rand === 3) {
        const itemDesc = item.getShortDesc();
        const msg = '<bold>The serpent uncoils, hissing.</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  playerDropItem: l10n  => {
    return (room, player, players, item) => {
      const rand = Random.inRange(1, 5);
      if (rand === 3) {
        const itemDesc = item.getShortDesc();
        const msg = '<bold>The python\'s tongue flickers over the ' + itemDesc + '</bold>';
        const toRoom = Broadcast.toRoom(room, this, player, players);
        toRoom({
          secondPartyMessage: msg,
          thirdPartyMessage: msg
        });
      }
    }
  },

  hit: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);
      const secondPartyMessage = Random.fromArray([
        'The enormous serpent wraps itself around your ' + hitLocation + ' and constricts...',
        'The snake clamps its fangs around your ' + hitLocation + ', refusing to let go.',
      ]);
      const thirdPartyMessage = Random.fromArray([
        'The python wraps itself around ' + player.combat.getDesc() + '\'s ' + hitLocation + '.',
        'The python bites ' + player.combat.getDesc() + ' in the ' + hitLocation + ' and clamps down.',
      ]);
      toRoom({
        secondPartyMessage,
        thirdPartyMessage,
      });

    }
  },

  damaged: function(l10n) {
    return function(room, player, players, hitLocation, damage) {
      const toRoom = Broadcast.toRoom(room, this, player, players);
      const secondPartyMessage = Random.fromArray([
        'The roach chitters as its antennae are bent at an odd angle.',
        'The roach\'s chitin splinters and cracks around its ' + hitLocation + '.',
        'The roach hisses as ichor oozes from its wounds.'
      ]);
      const thirdPartyMessage = Random.fromArray([
        'The roach chitters in pain as its ' + hitLocation + ' shatters.',
        'Hissing furiously, the roach rears its pincer-covered maw.',
        'Ichor oozes from the injured roach.'
      ]);
      toRoom({
          secondPartyMessage,
          thirdPartyMessage,
      });
    }
  },

};
<|endoftext|>


<commit_before>elation.require(['engine.things.generic'], function() {
  elation.component.add('engine.things.janusobject', function() {
    this.sidemap = {
      'back': THREE.FrontSide,
      'front': THREE.BackSide,
      'none': THREE.DoubleSide
    };
    this.postinit = function() {
      this.defineProperties({
        room: { type: 'object' },
        image_id: { type: 'string' },
        video_id: { type: 'string' },
        collision_id: { type: 'string' },
        websurface_id: { type: 'string' },
        lighting: { type: 'boolean', default: true },
        col: { type: 'string' },
        cull_face: { type: 'string', default: 'back' },
        blend_src: { type: 'string', default: 'src_alpha' },
        blend_dest: { type: 'string', default: 'one_minus_src_alpha' },
        rotate_axis: { type: 'string', default: '0 1 0' },
        rotate_deg_per_sec: { type: 'string' },
        props: { type: 'object' },
      });
    }
    this.createChildren = function() {
      if (this.objects['3d'].userData.loaded) {
        this.assignTextures();
      } else {
        elation.events.add(this.objects['3d'], 'asset_load', elation.bind(this, this.assignTextures));
      }
    }
    this.createForces = function() {
      var rotate_axis = this.properties.rotate_axis,
          rotate_speed = this.properties.rotate_deg_per_sec;
      if (rotate_axis && rotate_speed) {
        var speed = (rotate_speed * Math.PI/180);
        var axisparts = rotate_axis.split(' ');
        var axis = new THREE.Vector3().set(axisparts[0], axisparts[1], axisparts[2]);
        var q = new THREE.Quaternion().setFromAxisAngle(axis, speed);
        var vel = new THREE.Euler().setFromQuaternion(q);
        this.objects.dynamics.setAngularVelocity(vel);
      }

      if (this.properties.collision_id) {
        var collider = elation.engine.assets.find('model', this.properties.collision_id);
        if (collider.userData.loaded) {
          this.extractColliders(collider, true);
        } else {
          elation.events.add(collider, 'asset_load', elation.bind(this, function(ev) { this.extractColliders(collider, true); }) );
        }

      }
    }
    this.createObjectDOM = function() {
      return;
      if (this.properties.websurface_id) {
        var websurface = this.properties.room.websurfaces[this.properties.websurface_id];
        console.log('do a websurface: ' + this.properties.websurface_id, websurface);
        if (websurface) {
          var width = websurface.width || 1024,
              height = websurface.height || 768;

          var iframe = elation.html.create('iframe');
          iframe.src = 'http://www.github.com/';//websurface.src;
          var div = elation.html.create('div');
          div.className = 'janusweb_websurface ';
          div.appendChild(iframe);

          div.style.width = width + 'px';
          div.style.height = height + 'px';
          iframe.style.width = width + 'px';
          iframe.style.height = height + 'px';

          var obj = new THREE.CSS3DObject(div);
          obj.scale.set(1/width, 1/height, 1);
          this.objects['3d'].add(obj);
        }
      }
    }
    this.assignTextures = function() {
      var texture = false,
          color = false,
          blend_src = false,
          blend_dest = false,
          side = this.sidemap[this.properties.cull_face];

      if (this.properties.image_id) {
        texture = elation.engine.assets.find('image', this.properties.image_id);
      }
      if (this.properties.video_id) {
        var videoasset = elation.engine.assets.find('video', this.properties.video_id, true);
        if (videoasset) {
          texture = videoasset.getAsset();
          if (videoasset.sbs3d) {
            // TODO - to really support 3d video, we need to set offset based on which eye is being rendered
            texture.repeat.x = 0.5;
          }
          if (videoasset.auto_play) {
            texture.image.play();
          }
          elation.events.add(texture, 'videoframe', elation.bind(this, this.refresh));
        }
      }
      if (this.properties.col) {
        color = new THREE.Color();
        var col = this.properties.col;
        color.setRGB(col[0], col[1], col[2]);
      }
      if (this.properties.blend_src == 'src_color') {
        blend_src = THREE.SrcColorFactor;
      }
      if (this.properties.blend_dest == 'one_minus_src_alpha') {
        blend_dest = THREE.OneMinusSrcAlphaFactor;
      } else if (this.properties.blend_dest == 'one_minus_constant_color') {
        blend_dest = THREE.OneMinusConstantColorFactor;
      }
      this.objects['3d'].traverse(elation.bind(this, function(n) {
        if (n.material) {
          var materials = [];
          if (n.material instanceof THREE.MeshFaceMaterial) {
            //materials = [n.material.materials[1]];
            for (var i = 0; i < n.material.materials.length; i++) {
              var oldm = n.material.materials[i];
              var m = (this.properties.lighting != false ? new THREE.MeshPhongMaterial() : new THREE.MeshBasicMaterial());
              m.map = oldm.map;
              m.normalMap = oldm.normalMap;
              m.lightMap = oldm.lightMap;
              m.color.copy(oldm.color);
              m.transparent = oldm.transparent;
              materials.push(m);
            }
            //materials = n.material.materials;
            n.material.materials = materials;
          } else {
              var oldm = n.material;
              var m = (this.properties.lighting != false ? new THREE.MeshPhongMaterial() : new THREE.MeshBasicMaterial());
              m.map = oldm.map;
              m.normalMap = oldm.normalMap;
              m.lightMap = oldm.lightMap;
              m.color.copy(oldm.color);
              m.transparent = oldm.transparent;
              materials.push(m);
              n.material = m;
          }
          materials.forEach(elation.bind(this, function(m) {
            if (texture) {
              m.map = texture;
            }
            // FIXME - hack for transparent PNGs
            if (m.map && m.map.sourceFile && m.map.sourceFile.match(/[^0-9]\.(png|tga)$/)) {
              m.transparent = true;
            }
            if (color && m.color) {
              m.color.copy(color);
            }
            if (side) {
              m.side = side;
            }
            if (blend_src) m.blendSrc = blend_src;
            if (blend_dest) m.blendDst = blend_dest;
            m.needsUpdate = true;
          }));
          if (n.geometry) {
/*
            if ((n.geometry instanceof THREE.BufferGeometry && !n.geometry.attributes.normals) ||
                (n.geometry instanceof THREE.Geometry && !n.geometry.faceVertexNormals)) {
              n.geometry.computeFaceNormals();
              n.geometry.computeVertexNormals();
            }
*/
          }
        };
      }));
      this.refresh();
    }
  }, elation.engine.things.generic);
});
<commit_msg>Temporarily disabled lighting parameter<commit_after>elation.require(['engine.things.generic'], function() {
  elation.component.add('engine.things.janusobject', function() {
    this.sidemap = {
      'back': THREE.FrontSide,
      'front': THREE.BackSide,
      'none': THREE.DoubleSide
    };
    this.postinit = function() {
      this.defineProperties({
        room: { type: 'object' },
        image_id: { type: 'string' },
        video_id: { type: 'string' },
        collision_id: { type: 'string' },
        websurface_id: { type: 'string' },
        lighting: { type: 'boolean', default: true },
        col: { type: 'string' },
        cull_face: { type: 'string', default: 'back' },
        blend_src: { type: 'string', default: 'src_alpha' },
        blend_dest: { type: 'string', default: 'one_minus_src_alpha' },
        rotate_axis: { type: 'string', default: '0 1 0' },
        rotate_deg_per_sec: { type: 'string' },
        props: { type: 'object' },
      });
    }
    this.createChildren = function() {
      if (this.objects['3d'].userData.loaded) {
        this.assignTextures();
      } else {
        elation.events.add(this.objects['3d'], 'asset_load', elation.bind(this, this.assignTextures));
      }
    }
    this.createForces = function() {
      var rotate_axis = this.properties.rotate_axis,
          rotate_speed = this.properties.rotate_deg_per_sec;
      if (rotate_axis && rotate_speed) {
        var speed = (rotate_speed * Math.PI/180);
        var axisparts = rotate_axis.split(' ');
        var axis = new THREE.Vector3().set(axisparts[0], axisparts[1], axisparts[2]);
        var q = new THREE.Quaternion().setFromAxisAngle(axis, speed);
        var vel = new THREE.Euler().setFromQuaternion(q);
        this.objects.dynamics.setAngularVelocity(vel);
      }

      if (this.properties.collision_id) {
        var collider = elation.engine.assets.find('model', this.properties.collision_id);
        if (collider.userData.loaded) {
          this.extractColliders(collider, true);
        } else {
          elation.events.add(collider, 'asset_load', elation.bind(this, function(ev) { this.extractColliders(collider, true); }) );
        }

      }
    }
    this.createObjectDOM = function() {
      return;
      if (this.properties.websurface_id) {
        var websurface = this.properties.room.websurfaces[this.properties.websurface_id];
        console.log('do a websurface: ' + this.properties.websurface_id, websurface);
        if (websurface) {
          var width = websurface.width || 1024,
              height = websurface.height || 768;

          var iframe = elation.html.create('iframe');
          iframe.src = 'http://www.github.com/';//websurface.src;
          var div = elation.html.create('div');
          div.className = 'janusweb_websurface ';
          div.appendChild(iframe);

          div.style.width = width + 'px';
          div.style.height = height + 'px';
          iframe.style.width = width + 'px';
          iframe.style.height = height + 'px';

          var obj = new THREE.CSS3DObject(div);
          obj.scale.set(1/width, 1/height, 1);
          this.objects['3d'].add(obj);
        }
      }
    }
    this.assignTextures = function() {
      var texture = false,
          color = false,
          blend_src = false,
          blend_dest = false,
          side = this.sidemap[this.properties.cull_face];

      if (this.properties.image_id) {
        texture = elation.engine.assets.find('image', this.properties.image_id);
      }
      if (this.properties.video_id) {
        var videoasset = elation.engine.assets.find('video', this.properties.video_id, true);
        if (videoasset) {
          texture = videoasset.getAsset();
          if (videoasset.sbs3d) {
            // TODO - to really support 3d video, we need to set offset based on which eye is being rendered
            texture.repeat.x = 0.5;
          }
          if (videoasset.auto_play) {
            texture.image.play();
          }
          elation.events.add(texture, 'videoframe', elation.bind(this, this.refresh));
        }
      }
      if (this.properties.col) {
        color = new THREE.Color();
        var col = this.properties.col;
        color.setRGB(col[0], col[1], col[2]);
      }
      if (this.properties.blend_src == 'src_color') {
        blend_src = THREE.SrcColorFactor;
      }
      if (this.properties.blend_dest == 'one_minus_src_alpha') {
        blend_dest = THREE.OneMinusSrcAlphaFactor;
      } else if (this.properties.blend_dest == 'one_minus_constant_color') {
        blend_dest = THREE.OneMinusConstantColorFactor;
      }
      this.objects['3d'].traverse(elation.bind(this, function(n) {
        if (n.material) {
          var materials = [];
          if (n.material instanceof THREE.MeshFaceMaterial) {
            //materials = [n.material.materials[1]];
            for (var i = 0; i < n.material.materials.length; i++) {
              var oldm = n.material.materials[i];
              //var m = (this.properties.lighting != false ? new THREE.MeshPhongMaterial() : new THREE.MeshBasicMaterial());
              //var m = new THREE.MeshPhongMaterial();
              var m = new THREE.MeshStandardMaterial();
              m.map = oldm.map;
              m.normalMap = oldm.normalMap;
              m.lightMap = oldm.lightMap;
              m.color.copy(oldm.color);
              m.transparent = oldm.transparent;
              materials.push(m);
            }
            //materials = n.material.materials;
            n.material.materials = materials;
          } else {
              var oldm = n.material;
              //var m = (this.properties.lighting != false ? new THREE.MeshPhongMaterial() : new THREE.MeshBasicMaterial());
              var m = new THREE.MeshStandardMaterial();
              m.map = oldm.map;
              m.normalMap = oldm.normalMap;
              m.lightMap = oldm.lightMap;
              m.color.copy(oldm.color);
              m.transparent = oldm.transparent;
              materials.push(m);
              n.material = m;
          }
          materials.forEach(elation.bind(this, function(m) {
            if (texture) {
              m.map = texture;
            }
            // FIXME - hack for transparent PNGs
            if (m.map && m.map.sourceFile && m.map.sourceFile.match(/[^0-9]\.(png|tga)$/)) {
              m.transparent = true;
            }
            if (color && m.color) {
              m.color.copy(color);
            }
            if (side) {
              m.side = side;
            }
            if (blend_src) m.blendSrc = blend_src;
            if (blend_dest) m.blendDst = blend_dest;
            m.needsUpdate = true;
          }));
          if (n.geometry) {
/*
            if ((n.geometry instanceof THREE.BufferGeometry && !n.geometry.attributes.normals) ||
                (n.geometry instanceof THREE.Geometry && !n.geometry.faceVertexNormals)) {
              n.geometry.computeFaceNormals();
              n.geometry.computeVertexNormals();
            }
*/
          }
        };
      }));
      this.refresh();
    }
  }, elation.engine.things.generic);
});
<|endoftext|>