<commit_before>var saving = {
  todo: {
    html: false,
    css: false,
    javascript: false
  },
  _inprogress: false,
  inprogress: function (inprogress) {
    if (typeof inprogress === 'undefined') {
      return saving._inprogress;
    }

    saving._inprogress = inprogress;
    if (inprogress === false) {
      var panels = ['html','css','javascript'],
          todo;

      var save = function () {
        var todo = panels.pop();
        if (todo && saving.todo[todo]) {
          saving._inprogress = true;
          updateCode(todo, save);
          saving.todo[todo] = false;
        } else if (todo) {
          save();
        }
      };

      save();
    }
  }
};

// to allow for download button to be introduced via beta feature
$('a.save').click(function (event) {
  event.preventDefault();

  analytics.milestone();
  // if save is disabled, hitting save will trigger a reload
  var ajax = true;
  if (jsbin.saveDisabled === true) {
    ajax = false;
  }
  saveCode('save', ajax);

  return false;
});

var $shareLinks = $('#share .link');

$panelCheckboxes = $('#sharemenu #sharepanels input');

function updateSavedState() {
  var mapping = {
    live: 'output',
    javascript: 'js',
    css: 'css',
    html: 'html',
    console: 'console'
  };
  var query = $panelCheckboxes.filter(':checked').map(function () {
    return mapping[this.getAttribute('data-panel')];
  }).get().join(',');
  $shareLinks.each(function () {
    var path = this.getAttribute('data-path');
    var url = jsbin.getURL(false, path === '/') + path + (query && this.id !== 'livepreview' ? '?' + query : ''),
        nodeName = this.nodeName;
    if (nodeName === 'A') {
      this.href = url;
    } else if (nodeName === 'INPUT') {
      this.value = url;
    } else if (nodeName === 'TEXTAREA') {
      this.value = ('' + documentTitle + '<' + 'script src="' + jsbin.static + '/js/embed.js"><' + '/script>').replace(/<>"&/g, function (m) {
          return {
            '<': '<',
            '>': '>',
            '"': '"',
            '&': '&'
          }[m];
        });
    }
  });
}

$('#sharemenu').bind('open', function () {
  updateSavedState();
});

$document.on('saved', function () {
  updateSavedState();
  $shareLinks.closest('.menu').removeClass('hidden');

  $('#jsbinurl').attr('href', jsbin.getURL()).removeClass('hidden');
  $('#clone').removeClass('hidden');
});

var saveChecksum = jsbin.state.checksum || sessionStorage.getItem('checksum') || false;

// store it back on state
jsbin.state.checksum = saveChecksum;

if (saveChecksum) {
  // remove the disabled class, but also remove the cancelling event handlers
  $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
} else {
  $('#share div.disabled').one('click', function (event) {
    event.preventDefault();
    $('a.save').click();
  });
}

$document.one('saved', function () {
  $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
});

function onSaveError(jqXHR, panelId) {
  if (jqXHR.status === 413) {
    // Hijack the tip label to show an error message.
    $('#tip p').html('Sorry this bin is too large for us to save');
    $(document.documentElement).addClass('showtip');
  } else if (jqXHR.status === 403) {
    $document.trigger('tip', {
      type: 'error',
      content: 'I think there\'s something wrong with your session and I\'m unable to save. Refresh to fix this, you will not lose your code.'
    });
  } else if (panelId) {
    if (panelId) savingLabels[panelId].text('Saving...').animate({ opacity: 1 }, 100);
    window._console.error({message: 'Warning: Something went wrong while saving. Your most recent work is not saved.'});
  }
}

// only start live saving it they're allowed to (whereas save is disabled if they're following)
if (!jsbin.saveDisabled) {
  $('.code.panel .label .name').append('Saved');

  var savingLabels = {
    html: $('.panel.html .name span'),
    javascript: $('.panel.javascript .name span'),
    css: $('.panel.css .name span')
  };

  $document.bind('jsbinReady', function () {
    jsbin.panels.allEditors(function (panel) {
      panel.on('processor', function () {
        // if the url doesn't match the root - i.e. they've actually saved something then save on processor change
        if (jsbin.root !== jsbin.getURL()) {
          $document.trigger('codeChange', [{ panelId: panel.id }]);
        }
      });
    });

    $document.bind('codeChange', function (event, data) {
      // savingLabels[data.panelId].text('Saving');
      if (savingLabels[data.panelId]) {
        savingLabels[data.panelId].css({ 'opacity': 0 }).stop(true, true);
      }
    });

    $document.bind('saveComplete', throttle(function (event, data) {
      // show saved, then revert out animation
      savingLabels[data.panelId]
        .text('Saved')
        .stop(true, true)
        .animate({ opacity: 1 }, 100)
        .delay(1200)
        .animate({ opacity: 0 }, 500);
    }, 500));

    $document.bind('codeChange', throttle(function (event, data) {
      if (!data.panelId) {
        return;
      }

      if (jsbin.state.deleted) {
        return;
      }

      var panelId = data.panelId;

      jsbin.panels.savecontent();

      if (saving.inprogress()) {
        // queue up the request and wait
        saving.todo[panelId] = true;
        return;
      }

      saving.inprogress(true);

      // We force a full save if there's no checksum OR if there's no bin code/url
      if (!saveChecksum || !jsbin.state.code) {
        // create the bin and when the response comes back update the url
        saveCode('save', true);
      } else {
        updateCode(panelId);
      }
    }, 250));
  });
} else {
  $document.one('jsbinReady', function () {
    var shown = false;
    if (!jsbin.embed && !jsbin.sandbox) {
      $document.on('codeChange', function (event, data) {
        if (!data.onload && !shown && data.origin !== 'setValue') {
          shown = true;
          var ismac = navigator.userAgent.indexOf(' Mac ') !== -1;
          var cmd = ismac ? '⌘' : 'ctrl';
          var shift = ismac ? '⇧' : 'shift';
          var plus = ismac ? '' : '+';

          $document.trigger('tip', {
            type: 'notification',
            content: 'You\'re currently viewing someone else\'s live stream, but you can clone your own copy (' + cmd + plus + shift + plus + 'S) at any time to save your edits'
          });
        }
      });
    }
  });
}

function compressData (keys, obj) {
  obj.compressed = keys;
  keys.split(',').forEach(function (key) {
    obj[key] = LZString.compress(obj[key]);
  });
}

function updateCode(panelId, callback) {
  var panelSettings = {};

  if (jsbin.state.processors) {
    panelSettings.processors = jsbin.state.processors;
  }

  var data = {
    code: jsbin.state.code,
    revision: jsbin.state.revision,
    method: 'update',
    panel: panelId,
    content: editors[panelId].getCode(),
    checksum: saveChecksum,
    settings: JSON.stringify(panelSettings),
  };

  if (jsbin.settings.useCompression) {
    compressData('content', data);
  }

  $.ajax({
    url: jsbin.getURL() + '/save',
    data: data,
    type: 'post',
    dataType: 'json',
    headers: {'Accept': 'application/json'},
    success: function (data) {
      $document.trigger('saveComplete', { panelId: panelId });
      if (data.error) {
        saveCode('save', true, function (data) {
          // savedAlready = data.checksum;
        });
      }
    },
    error: function (jqXHR) {
      onSaveError(jqXHR, panelId);
    },
    complete: function () {
      saving.inprogress(false);
      callback && callback();
    }
  });
}

$('a.clone').click(function (event) {
  event.preventDefault();

  // save our panel layout - assumes our user is happy with this layout
  jsbin.panels.save();
  analytics.clone();

  var $form = setupform('save,new');
  $form.submit();

  return false;
});

function setupform(method) {
var $form = $('form#saveform').empty()
    .append('<input type="hidden" name="javascript" />')
    .append('<input type="hidden" name="html" />')
    .append('<input type="hidden" name="css" />')
    .append('<input type="hidden" name="method" />')
    .append('<input type="hidden" name="_csrf" value="' + jsbin.state.token + '" />')
    .append('<input type="hidden" name="settings" />');

  var settings = {};

  if (jsbin.state.processors) {
    settings.processors = jsbin.state.processors;
  }

  // this prevents new revisions forking off the welcome bin
  // because it's looking silly!
  if (jsbin.state.code === 'welcome') {
    $form.attr('action', '/save');
  }

  $form.find('input[name=settings]').val(JSON.stringify(settings));
  $form.find('input[name=javascript]').val(editors.javascript.getCode());
  $form.find('input[name=css]').val(editors.css.getCode());
  $form.find('input[name=html]').val(editors.html.getCode());
  $form.find('input[name=method]').val(method);

  return $form;
}

function pad(n){
  return n<10 ? '0'+n : n
}

function ISODateString(d){
  return d.getFullYear()+'-'
    + pad(d.getMonth()+1)+'-'
    + pad(d.getDate())+'T'
    + pad(d.getHours())+':'
    + pad(d.getMinutes())+':'
    + pad(d.getSeconds())+'Z'
}

function saveCode(method, ajax, ajaxCallback) {
  // create form and post to it
  var $form = setupform(method);
  // save our panel layout - assumes our user is happy with this layout
  jsbin.panels.save();
  jsbin.panels.saveOnExit = true;

  var data = $form.serializeArray().reduce(function(obj, data) {
    obj[data.name] = data.value;
    return obj;
  }, {});

  if (jsbin.settings.useCompression) {
    compressData('html,css,javascript', data);
  }

  if (ajax) {
    $.ajax({
      url: $form.attr('action'),
      data: data,
      dataType: 'json',
      type: 'post',
      headers: {'Accept': 'application/json'},
      success: function (data) {
        var $binGroup,
            edit;

        $form.attr('action', data.url + '/save');
        if (ajaxCallback) {
          ajaxCallback(data);
        }

        sessionStorage.setItem('checksum', data.checksum);
        saveChecksum = data.checksum;

        jsbin.state.checksum = saveChecksum;
        jsbin.state.code = data.code;
        jsbin.state.revision = data.revision;
        jsbin.state.metadata = { name: jsbin.user.name };

        // getURL(true) gets the jsbin without the root attached
        // $binGroup = $('#history tr[data-url="' + jsbin.getURL(true) + '"]');
        // edit = data.edit.replace(location.protocol + '//' + window.location.host, '') + window.location.search;
        // $binGroup.find('td.url a span.first').removeClass('first');
        // $binGroup.before('
' + data.code + '/' + data.revision + '/	Just now	' + data.title + '
');

        if (window.history && window.history.pushState) {
          // updateURL(edit);
          window.history.pushState(null, '', jsbin.getURL() + '/edit');
          sessionStorage.setItem('url', jsbin.getURL());
        } else {
          window.location.hash = data.edit;
        }

        $document.trigger('saved');
      },
      error: function (jqXHR) {
        onSaveError(jqXHR, null);
      },
      complete: function () {
        saving.inprogress(false);
      }
    });
  } else {
    $form.submit();
  }
}

/**
 * Returns the similar part of two strings
 * @param  {String} a first string
 * @param  {String} b second string
 * @return {String}   common substring
 */
function sameStart(a, b) {
  if (a == b) return a;

  var tmp = b.slice(0, 1);
  while (a.indexOf(b.slice(0, tmp.length + 1)) === 0) {
    tmp = b.slice(0, tmp.length + 1);
  }

  return tmp;
}

/*

// refresh the window when we popstate, because for now we don't do an xhr to
// inject the panel content...yet.
window.onpopstate = function onpopstate(event) {
  // ignore the first popstate event, because that comes from the browser...
  if (!onpopstate.first) window.location.reload();
  else onpopstate.first = false;
};

onpopstate.first = true;

function updateURL(path) {
  var old = location.pathname,
      back = true,
      same = sameStart(old, path);
      sameAt = same.length;

  if (updateURL.timer) window.cancelAnimationFrame(updateURL.timer);

  var run = function () {
    if (location.pathname !== path) {
      updateURL.timer = window.requestAnimationFrame(run);
    }

    if (location.pathname !== same) {
      if (back) {
        history.replaceState({ path: path }, '', location.pathname.slice(0, -1));
      } else {
        history.replaceState({ path: path }, '', path.slice(0, location.pathname.length + 1));
      }
    } else {
      back = false;
      history.replaceState({ path: path }, '', path.slice(0, sameAt + 2));
    }
  };

  history.pushState({ path: path }, '', location.pathname.slice(0, -1));

  run();
}

*/
<commit_msg>Rename compressData to compressKeys<commit_after>var saving = {
  todo: {
    html: false,
    css: false,
    javascript: false
  },
  _inprogress: false,
  inprogress: function (inprogress) {
    if (typeof inprogress === 'undefined') {
      return saving._inprogress;
    }

    saving._inprogress = inprogress;
    if (inprogress === false) {
      var panels = ['html','css','javascript'],
          todo;

      var save = function () {
        var todo = panels.pop();
        if (todo && saving.todo[todo]) {
          saving._inprogress = true;
          updateCode(todo, save);
          saving.todo[todo] = false;
        } else if (todo) {
          save();
        }
      };

      save();
    }
  }
};

// to allow for download button to be introduced via beta feature
$('a.save').click(function (event) {
  event.preventDefault();

  analytics.milestone();
  // if save is disabled, hitting save will trigger a reload
  var ajax = true;
  if (jsbin.saveDisabled === true) {
    ajax = false;
  }
  saveCode('save', ajax);

  return false;
});

var $shareLinks = $('#share .link');

$panelCheckboxes = $('#sharemenu #sharepanels input');

function updateSavedState() {
  var mapping = {
    live: 'output',
    javascript: 'js',
    css: 'css',
    html: 'html',
    console: 'console'
  };
  var query = $panelCheckboxes.filter(':checked').map(function () {
    return mapping[this.getAttribute('data-panel')];
  }).get().join(',');
  $shareLinks.each(function () {
    var path = this.getAttribute('data-path');
    var url = jsbin.getURL(false, path === '/') + path + (query && this.id !== 'livepreview' ? '?' + query : ''),
        nodeName = this.nodeName;
    if (nodeName === 'A') {
      this.href = url;
    } else if (nodeName === 'INPUT') {
      this.value = url;
    } else if (nodeName === 'TEXTAREA') {
      this.value = ('' + documentTitle + '<' + 'script src="' + jsbin.static + '/js/embed.js"><' + '/script>').replace(/<>"&/g, function (m) {
          return {
            '<': '<',
            '>': '>',
            '"': '"',
            '&': '&'
          }[m];
        });
    }
  });
}

$('#sharemenu').bind('open', function () {
  updateSavedState();
});

$document.on('saved', function () {
  updateSavedState();
  $shareLinks.closest('.menu').removeClass('hidden');

  $('#jsbinurl').attr('href', jsbin.getURL()).removeClass('hidden');
  $('#clone').removeClass('hidden');
});

var saveChecksum = jsbin.state.checksum || sessionStorage.getItem('checksum') || false;

// store it back on state
jsbin.state.checksum = saveChecksum;

if (saveChecksum) {
  // remove the disabled class, but also remove the cancelling event handlers
  $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
} else {
  $('#share div.disabled').one('click', function (event) {
    event.preventDefault();
    $('a.save').click();
  });
}

$document.one('saved', function () {
  $('#share div.disabled').removeClass('disabled').unbind('click mousedown mouseup');
});

function onSaveError(jqXHR, panelId) {
  if (jqXHR.status === 413) {
    // Hijack the tip label to show an error message.
    $('#tip p').html('Sorry this bin is too large for us to save');
    $(document.documentElement).addClass('showtip');
  } else if (jqXHR.status === 403) {
    $document.trigger('tip', {
      type: 'error',
      content: 'I think there\'s something wrong with your session and I\'m unable to save. Refresh to fix this, you will not lose your code.'
    });
  } else if (panelId) {
    if (panelId) savingLabels[panelId].text('Saving...').animate({ opacity: 1 }, 100);
    window._console.error({message: 'Warning: Something went wrong while saving. Your most recent work is not saved.'});
  }
}

// only start live saving it they're allowed to (whereas save is disabled if they're following)
if (!jsbin.saveDisabled) {
  $('.code.panel .label .name').append('Saved');

  var savingLabels = {
    html: $('.panel.html .name span'),
    javascript: $('.panel.javascript .name span'),
    css: $('.panel.css .name span')
  };

  $document.bind('jsbinReady', function () {
    jsbin.panels.allEditors(function (panel) {
      panel.on('processor', function () {
        // if the url doesn't match the root - i.e. they've actually saved something then save on processor change
        if (jsbin.root !== jsbin.getURL()) {
          $document.trigger('codeChange', [{ panelId: panel.id }]);
        }
      });
    });

    $document.bind('codeChange', function (event, data) {
      // savingLabels[data.panelId].text('Saving');
      if (savingLabels[data.panelId]) {
        savingLabels[data.panelId].css({ 'opacity': 0 }).stop(true, true);
      }
    });

    $document.bind('saveComplete', throttle(function (event, data) {
      // show saved, then revert out animation
      savingLabels[data.panelId]
        .text('Saved')
        .stop(true, true)
        .animate({ opacity: 1 }, 100)
        .delay(1200)
        .animate({ opacity: 0 }, 500);
    }, 500));

    $document.bind('codeChange', throttle(function (event, data) {
      if (!data.panelId) {
        return;
      }

      if (jsbin.state.deleted) {
        return;
      }

      var panelId = data.panelId;

      jsbin.panels.savecontent();

      if (saving.inprogress()) {
        // queue up the request and wait
        saving.todo[panelId] = true;
        return;
      }

      saving.inprogress(true);

      // We force a full save if there's no checksum OR if there's no bin code/url
      if (!saveChecksum || !jsbin.state.code) {
        // create the bin and when the response comes back update the url
        saveCode('save', true);
      } else {
        updateCode(panelId);
      }
    }, 250));
  });
} else {
  $document.one('jsbinReady', function () {
    var shown = false;
    if (!jsbin.embed && !jsbin.sandbox) {
      $document.on('codeChange', function (event, data) {
        if (!data.onload && !shown && data.origin !== 'setValue') {
          shown = true;
          var ismac = navigator.userAgent.indexOf(' Mac ') !== -1;
          var cmd = ismac ? '⌘' : 'ctrl';
          var shift = ismac ? '⇧' : 'shift';
          var plus = ismac ? '' : '+';

          $document.trigger('tip', {
            type: 'notification',
            content: 'You\'re currently viewing someone else\'s live stream, but you can clone your own copy (' + cmd + plus + shift + plus + 'S) at any time to save your edits'
          });
        }
      });
    }
  });
}

function compressKeys(keys, obj) {
  obj.compressed = keys;
  keys.split(',').forEach(function (key) {
    obj[key] = LZString.compress(obj[key]);
  });
}

function updateCode(panelId, callback) {
  var panelSettings = {};

  if (jsbin.state.processors) {
    panelSettings.processors = jsbin.state.processors;
  }

  var data = {
    code: jsbin.state.code,
    revision: jsbin.state.revision,
    method: 'update',
    panel: panelId,
    content: editors[panelId].getCode(),
    checksum: saveChecksum,
    settings: JSON.stringify(panelSettings),
  };

  if (jsbin.settings.useCompression) {
    compressKeys('content', data);
  }

  $.ajax({
    url: jsbin.getURL() + '/save',
    data: data,
    type: 'post',
    dataType: 'json',
    headers: {'Accept': 'application/json'},
    success: function (data) {
      $document.trigger('saveComplete', { panelId: panelId });
      if (data.error) {
        saveCode('save', true, function (data) {
          // savedAlready = data.checksum;
        });
      }
    },
    error: function (jqXHR) {
      onSaveError(jqXHR, panelId);
    },
    complete: function () {
      saving.inprogress(false);
      callback && callback();
    }
  });
}

$('a.clone').click(function (event) {
  event.preventDefault();

  // save our panel layout - assumes our user is happy with this layout
  jsbin.panels.save();
  analytics.clone();

  var $form = setupform('save,new');
  $form.submit();

  return false;
});

function setupform(method) {
var $form = $('form#saveform').empty()
    .append('<input type="hidden" name="javascript" />')
    .append('<input type="hidden" name="html" />')
    .append('<input type="hidden" name="css" />')
    .append('<input type="hidden" name="method" />')
    .append('<input type="hidden" name="_csrf" value="' + jsbin.state.token + '" />')
    .append('<input type="hidden" name="settings" />');

  var settings = {};

  if (jsbin.state.processors) {
    settings.processors = jsbin.state.processors;
  }

  // this prevents new revisions forking off the welcome bin
  // because it's looking silly!
  if (jsbin.state.code === 'welcome') {
    $form.attr('action', '/save');
  }

  $form.find('input[name=settings]').val(JSON.stringify(settings));
  $form.find('input[name=javascript]').val(editors.javascript.getCode());
  $form.find('input[name=css]').val(editors.css.getCode());
  $form.find('input[name=html]').val(editors.html.getCode());
  $form.find('input[name=method]').val(method);

  return $form;
}

function pad(n){
  return n<10 ? '0'+n : n
}

function ISODateString(d){
  return d.getFullYear()+'-'
    + pad(d.getMonth()+1)+'-'
    + pad(d.getDate())+'T'
    + pad(d.getHours())+':'
    + pad(d.getMinutes())+':'
    + pad(d.getSeconds())+'Z'
}

function saveCode(method, ajax, ajaxCallback) {
  // create form and post to it
  var $form = setupform(method);
  // save our panel layout - assumes our user is happy with this layout
  jsbin.panels.save();
  jsbin.panels.saveOnExit = true;

  var data = $form.serializeArray().reduce(function(obj, data) {
    obj[data.name] = data.value;
    return obj;
  }, {});

  if (jsbin.settings.useCompression) {
    compressKeys('html,css,javascript', data);
  }

  if (ajax) {
    $.ajax({
      url: $form.attr('action'),
      data: data,
      dataType: 'json',
      type: 'post',
      headers: {'Accept': 'application/json'},
      success: function (data) {
        var $binGroup,
            edit;

        $form.attr('action', data.url + '/save');
        if (ajaxCallback) {
          ajaxCallback(data);
        }

        sessionStorage.setItem('checksum', data.checksum);
        saveChecksum = data.checksum;

        jsbin.state.checksum = saveChecksum;
        jsbin.state.code = data.code;
        jsbin.state.revision = data.revision;
        jsbin.state.metadata = { name: jsbin.user.name };

        // getURL(true) gets the jsbin without the root attached
        // $binGroup = $('#history tr[data-url="' + jsbin.getURL(true) + '"]');
        // edit = data.edit.replace(location.protocol + '//' + window.location.host, '') + window.location.search;
        // $binGroup.find('td.url a span.first').removeClass('first');
        // $binGroup.before('
' + data.code + '/' + data.revision + '/	Just now	' + data.title + '
');

        if (window.history && window.history.pushState) {
          // updateURL(edit);
          window.history.pushState(null, '', jsbin.getURL() + '/edit');
          sessionStorage.setItem('url', jsbin.getURL());
        } else {
          window.location.hash = data.edit;
        }

        $document.trigger('saved');
      },
      error: function (jqXHR) {
        onSaveError(jqXHR, null);
      },
      complete: function () {
        saving.inprogress(false);
      }
    });
  } else {
    $form.submit();
  }
}

/**
 * Returns the similar part of two strings
 * @param  {String} a first string
 * @param  {String} b second string
 * @return {String}   common substring
 */
function sameStart(a, b) {
  if (a == b) return a;

  var tmp = b.slice(0, 1);
  while (a.indexOf(b.slice(0, tmp.length + 1)) === 0) {
    tmp = b.slice(0, tmp.length + 1);
  }

  return tmp;
}

/*

// refresh the window when we popstate, because for now we don't do an xhr to
// inject the panel content...yet.
window.onpopstate = function onpopstate(event) {
  // ignore the first popstate event, because that comes from the browser...
  if (!onpopstate.first) window.location.reload();
  else onpopstate.first = false;
};

onpopstate.first = true;

function updateURL(path) {
  var old = location.pathname,
      back = true,
      same = sameStart(old, path);
      sameAt = same.length;

  if (updateURL.timer) window.cancelAnimationFrame(updateURL.timer);

  var run = function () {
    if (location.pathname !== path) {
      updateURL.timer = window.requestAnimationFrame(run);
    }

    if (location.pathname !== same) {
      if (back) {
        history.replaceState({ path: path }, '', location.pathname.slice(0, -1));
      } else {
        history.replaceState({ path: path }, '', path.slice(0, location.pathname.length + 1));
      }
    } else {
      back = false;
      history.replaceState({ path: path }, '', path.slice(0, sameAt + 2));
    }
  };

  history.pushState({ path: path }, '', location.pathname.slice(0, -1));

  run();
}

*/
<|endoftext|>


<commit_before>/**
 * @file commandHandler
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

const parseArgs = require('command-line-args');
const COLOR = require('chalk');

/**
 * Handles Bastion's commands
 * @param {Message} message Discord.js message object
 * @returns {void}
 */
module.exports = async message => {
  try {
    let guild = await message.client.db.get(`SELECT prefix, ignoredChannelIDs, ignoredRoleIDs FROM guildSettings WHERE guildID=${message.guild.id}`);

    if (!message.guild.prefix || message.guild.prefix !== guild.prefix) {
      message.guild.prefix = guild.prefix;
    }

    if (!message.content.startsWith(guild.prefix)) return;

    if (guild.ignoredChannelIDs) {
      if (guild.ignoredChannelIDs.split(' ').includes(message.channel.id)) return;
    }

    if (guild.ignoredRoleIDs) {
      let ignoredRoleIDs = guild.ignoredRoleIDs.split(' ');
      for (let roleID of ignoredRoleIDs) {
        if (message.member.roles.has(roleID)) return;
      }
    }

    let args = message.content.split(' ');
    let command = args.shift().slice(guild.prefix.length).toLowerCase();

    let cmd;
    if (message.client.commands.has(command)) {
      cmd = message.client.commands.get(command);
    }
    else if (message.client.aliases.has(command)) {
      cmd = message.client.commands.get(message.client.aliases.get(command));
    }
    else return;

    message.client.log.console(`\n[${new Date()}]`);
    message.client.log.console(COLOR.green('[COMMAND]: ') + guild.prefix + command);
    message.client.log.console(COLOR.green('[ARGUMENTs]: ') + (args.join(' ') || COLOR.yellow('No arguments to execute')));
    message.client.log.console(`${COLOR.green('[SERVER]:')} ${message.guild} ${COLOR.cyan(`<#${message.guild.id}>`)}`);
    message.client.log.console(`${COLOR.green('[CHANNEL]:')} #${message.channel.name} ${COLOR.cyan(message.channel)}`);
    message.client.log.console(`${COLOR.green('[USER]:')} ${message.author.tag} ${COLOR.cyan(`${message.author}`)}`);

    if (!cmd.config.enabled) {
      return message.client.log.info('This command is disabled.');
    }
    cmd.run(message.client, message, parseArgs(cmd.config.argsDefinitions, { argv: args, partial: true }));
  }
  catch (e) {
    message.client.log.error(e);
  }
};
<commit_msg>Improved command handler * Allowed guild admins to bypass ignored channels and roles<commit_after>/**
 * @file commandHandler
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

const parseArgs = require('command-line-args');
const COLOR = require('chalk');

/**
 * Handles Bastion's commands
 * @param {Message} message Discord.js message object
 * @returns {void}
 */
module.exports = async message => {
  try {
    let guild = await message.client.db.get(`SELECT prefix, ignoredChannelIDs, ignoredRoleIDs FROM guildSettings WHERE guildID=${message.guild.id}`);

    if (!message.guild.prefix || message.guild.prefix !== guild.prefix) {
      message.guild.prefix = guild.prefix;
    }

    if (!message.content.startsWith(guild.prefix)) return;

    if (!message.member.hasPermission('ADMINISTRATOR')) {
      if (guild.ignoredChannelIDs) {
        if (guild.ignoredChannelIDs.split(' ').includes(message.channel.id)) return;
      }

      if (guild.ignoredRoleIDs) {
        let ignoredRoleIDs = guild.ignoredRoleIDs.split(' ');
        for (let roleID of ignoredRoleIDs) {
          if (message.member.roles.has(roleID)) return;
        }
      }
    }

    let args = message.content.split(' ');
    let command = args.shift().slice(guild.prefix.length).toLowerCase();

    let cmd;
    if (message.client.commands.has(command)) {
      cmd = message.client.commands.get(command);
    }
    else if (message.client.aliases.has(command)) {
      cmd = message.client.commands.get(message.client.aliases.get(command));
    }
    else return;

    message.client.log.console(`\n[${new Date()}]`);
    message.client.log.console(COLOR.green('[COMMAND]: ') + guild.prefix + command);
    message.client.log.console(COLOR.green('[ARGUMENTs]: ') + (args.join(' ') || COLOR.yellow('No arguments to execute')));
    message.client.log.console(`${COLOR.green('[SERVER]:')} ${message.guild} ${COLOR.cyan(`<#${message.guild.id}>`)}`);
    message.client.log.console(`${COLOR.green('[CHANNEL]:')} #${message.channel.name} ${COLOR.cyan(message.channel)}`);
    message.client.log.console(`${COLOR.green('[USER]:')} ${message.author.tag} ${COLOR.cyan(`${message.author}`)}`);

    if (!cmd.config.enabled) {
      return message.client.log.info('This command is disabled.');
    }
    cmd.run(message.client, message, parseArgs(cmd.config.argsDefinitions, { argv: args, partial: true }));
  }
  catch (e) {
    message.client.log.error(e);
  }
};
<|endoftext|>


<commit_before>var uuid = require('node-uuid'),
    jsface = require('jsface'),
    url = require('url'),
    META_KEY = 'x-postman-meta',

    ConvertResult = function (status, message) {
        this.status = status;
        this.message = message;
    },

    Swagger2Postman = jsface.Class({
        constructor: function (options) {
            this.collectionJson = {
                'id': '',
                'name': '',
                'description': '',
                'order': [],
                'folders': [],
                'timestamp': 1413302258635,
                'synced': false,
                'requests': []
            };
            this.basePath = '';
            this.collectionId = '';
            this.folders = {};
            this.baseParams = {};
            this.logger = function () {
            };

            this.options = options || {};

            this.options.includeQueryParams = typeof (this.options.includeQueryParams) == 'undefined' ?
                                                        true : this.options.includeQueryParams;
        },

        setLogger: function (func) {
            this.logger = func;
        },

        validate: function (json) {
            if (!json.hasOwnProperty('swagger') || json.swagger !== '2.0') {
                return new ConvertResult('failed', 'Must contain a swagger field (2.0)');
            }

            if (!json.hasOwnProperty('info')) {
                return new ConvertResult('failed', 'Must contain an info object');
            }
            else {
                var info = json.info;
                if (!info || !info.title) {
                    return new ConvertResult('failed', 'Must contain info.title');
                }
            }

            return new ConvertResult('passed', '');
        },

        setBasePath: function (json) {
            this.basePath = '';
            if (json.host) {
                this.basePath = json.host;
            }
            if (json.basePath) {
                this.basePath += json.basePath;
            }

            if (json.schemes && json.schemes.indexOf('https') != -1) {
                this.basePath = 'https://' + this.basePath;
            }
            else {
                this.basePath = 'http://' + this.basePath;
            }

            if (!this.endsWith(this.basePath, '/')) {
                this.basePath += '/';
            }
        },

        getFolderNameForPath: function (pathUrl) {
            if (pathUrl == '/') {
                return null;
            }
            var segments = pathUrl.split('/'),
                numSegments = segments.length,
                folderName = null;
            this.logger('Getting folder name for path: ' + pathUrl);
            this.logger('Segments: ' + JSON.stringify(segments));
            if (numSegments > 1) {
                folderName = segments[1];

                // create a folder for this path url
                if (!this.folders[folderName]) {
                    this.folders[folderName] = this.createNewFolder(folderName);
                }
                this.logger('For path ' + pathUrl + ', returning folderName ' + this.folders[folderName].name);
                return this.folders[folderName].name;
            }
            else {
                this.logger('Error - path MUST begin with /');
                return null;
            }
        },

        createNewFolder: function (name) {
            var newFolder = {
                'id': uuid.v4(),
                'name': name,
                'description': 'Folder for ' + name,
                'order': [],
                'collection_name': this.collectionJson.name,
                'collection_id': this.collectionId,
                'collection': this.collectionId
            };
            this.logger('Created folder ' + newFolder.name);
            return newFolder;
        },

        handleInfo: function (json) {
            this.collectionJson.name = json.info.title;
            this.collectionJson.description = json.info.description;
        },

        getParamsForPathItem: function (oldParams, newParams) {
            var retVal = {},
                numOldParams,
                numNewParams,
                i,
                parts,
                lastPart,
                getBaseParam;

            oldParams = oldParams || [];
            newParams = newParams || [];

            numOldParams = oldParams.length;
            numNewParams = newParams.length;

            for (i = 0; i < numOldParams; i++) {
                if (oldParams[i].$ref) {
                    // this is a ref
                    if (oldParams[i].$ref.indexOf('#/parameters') === 0) {
                        parts = oldParams[i].$ref.split('/');
                        lastPart = parts[parts.length - 1];
                        getBaseParam = this.baseParams[lastPart];
                        retVal[lastPart] = getBaseParam;
                    }
                }
                else {
                    retVal[oldParams[i].name] = oldParams[i];
                }
            }

            for (i = 0; i < numNewParams; i++) {
                if (newParams[i].$ref) {
                    // this is a ref
                    if (newParams[i].$ref.indexOf('#/parameters') === 0) {
                        parts = newParams[i].$ref.split('/');
                        lastPart = parts[parts.length - 1];
                        getBaseParam = this.baseParams[lastPart];
                        retVal[lastPart] = getBaseParam;
                    }
                }
                else {
                    retVal[newParams[i].name] = newParams[i];
                }
            }

            return retVal;
        },

        addOperationToFolder: function (path, method, operation, folderName, params) {
            var root = this,
                request = {
                    'id': uuid.v4(),
                    'headers': '',
                    'url': '',
                    'pathVariables': {},
                    'preRequestScript': '',
                    'method': 'GET',
                    'data': [],
                    'dataMode': 'params',
                    'description': operation.description || '',
                    'descriptionFormat': 'html',
                    'time': '',
                    'version': 2,
                    'responses': [],
                    'tests': '',
                    'collectionId': root.collectionId,
                    'synced': false
                },
                thisParams = this.getParamsForPathItem(params, operation.parameters),
                hasQueryParams = false,
                param,
                requestAttr;

            if (path.length > 0 && path[0] === '/') {
                path = path.substring(1);
            }
            request.url = decodeURI(url.resolve(this.basePath, path));
            request.method = method;
            request.name = operation.summary;
            request.time = (new Date()).getTime();

            // Handle custom swagger attributes for postman aws integration
            if (operation[META_KEY]) {
                for (requestAttr in operation[META_KEY]) {
                    if (operation[META_KEY].hasOwnProperty(requestAttr)) {
                        request[requestAttr] = operation[META_KEY][requestAttr];
                    }
                }
            }

            // set data and headers
            for (param in thisParams) {
                if (thisParams.hasOwnProperty(param) && thisParams[param]) {
                    this.logger('Processing param: ' + JSON.stringify(param));
                    if (thisParams[param].in === 'query' && this.options.includeQueryParams !== false) {
                        if (!hasQueryParams) {
                            hasQueryParams = true;
                            request.url += '?';
                        }
                        request.url += thisParams[param].name + '={{' + thisParams[param].name + '}}&';
                    }

                    else if (thisParams[param].in === 'header') {
                        request.headers += thisParams[param].name + ': {{' + thisParams[param].name + '}}\n';
                    }

                    else if (thisParams[param].in === 'body') {
                        request.dataMode = 'raw';
                        request.data = thisParams[param].description;
                    }

                    else if (thisParams[param].in === 'formData') {
                        request.dataMode = 'params';
                        request.data.push({
                            'key': thisParams[param].name,
                            'value': '{{' + thisParams[param].name + '}}',
                            'type': 'text',
                            'enabled': true
                        });
                    } // (thisParams[param].in === 'path') case not handled
                }
            }

            if (hasQueryParams && this.endsWith(request.url, '&')) {
                request.url = request.url.slice(0, -1);
            }

            this.collectionJson.requests.push(request);
            if (folderName !== null) {
                this.folders[folderName].order.push(request.id);
            }
            else {
                this.collectionJson.order.push(request.id);
            }
        },

        addPathItemToFolder: function (path, pathItem, folderName) {
            if (pathItem.$ref) {
                this.logger('Error - cannot handle $ref attributes');
                return;
            }

            var paramsForPathItem = this.getParamsForPathItem(this.baseParams, pathItem.parameters),
                acceptedPostmanVerbs = [
                    'get', 'put', 'post', 'patch', 'delete', 'copy', 'head', 'options',
                    'link', 'unlink', 'purge', 'lock', 'unlock', 'propfind', 'view'],
                numVerbs = acceptedPostmanVerbs.length,
                i,
                verb;

            // replace path variables {petId} with {{..}}
            if (path) {
                path = path.replace('{', '{{').replace('}', '}}');
            }

            for (i = 0; i < numVerbs; i++) {
                verb = acceptedPostmanVerbs[i];
                if (pathItem[verb]) {
                    this.addOperationToFolder(
                        path,
                        verb.toUpperCase(),
                        pathItem[verb],
                        folderName,
                        paramsForPathItem
                    );
                }
            }
        },

        handlePaths: function (json) {
            var paths = json.paths,
                path,
                folderName;

            // Add a folder for each path
            for (path in paths) {
                if (paths.hasOwnProperty(path)) {
                    folderName = this.getFolderNameForPath(path);
                    this.logger('Adding path item. path = ' + path + '   folder = ' + folderName);
                    this.addPathItemToFolder(path, paths[path], folderName);
                }
            }
        },

        handleParams: function (params, level) {
            if (!params) {
                return;
            }
            if (level === 'collection') {
                // base params
                for (var param in params) {
                    if (params.hasOwnProperty(param)) {
                        this.logger('Adding collection param: ' + param);
                        this.baseParams[param] = params[param];
                    }
                }
            }
        },

        addFoldersToCollection: function () {
            var folderName;
            for (folderName in this.folders) {
                if (this.folders.hasOwnProperty(folderName)) {
                    this.collectionJson.folders.push(this.folders[folderName]);
                }
            }
        },

        convert: function (json) {
            var validationResult = this.validate(json);
            if (validationResult.status === 'failed') {
                // error
                return validationResult;
            }

            this.collectionId = uuid.v4();

            this.handleParams(json.parameters, 'collection');

            this.handleInfo(json);

            this.setBasePath(json);

            this.handlePaths(json);

            this.addFoldersToCollection();

            this.collectionJson.id = this.collectionId;
            // this.logger(JSON.stringify(this.collectionJson));
            this.logger('Swagger converted successfully');

            validationResult.collection = this.collectionJson;

            return validationResult;
        },

        // since travis doesnt support es6
        endsWith: function (str, suffix) {
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }
    });

module.exports = Swagger2Postman;
<commit_msg>Zendesk#4350 - SwaggerConverter working with consumes:urlencoded<commit_after>var uuid = require('node-uuid'),
    jsface = require('jsface'),
    url = require('url'),
    META_KEY = 'x-postman-meta',

    ConvertResult = function (status, message) {
        this.status = status;
        this.message = message;
    },

    Swagger2Postman = jsface.Class({
        constructor: function (options) {
            this.collectionJson = {
                'id': '',
                'name': '',
                'description': '',
                'order': [],
                'folders': [],
                'timestamp': 1413302258635,
                'synced': false,
                'requests': []
            };
            this.basePath = '';
            this.collectionId = '';
            this.folders = {};
            this.baseParams = {};
            this.logger = function () {
            };

            this.options = options || {};

            this.options.includeQueryParams = typeof (this.options.includeQueryParams) == 'undefined' ?
                                                        true : this.options.includeQueryParams;
        },

        setLogger: function (func) {
            this.logger = func;
        },

        validate: function (json) {
            if (!json.hasOwnProperty('swagger') || json.swagger !== '2.0') {
                return new ConvertResult('failed', 'Must contain a swagger field (2.0)');
            }

            if (!json.hasOwnProperty('info')) {
                return new ConvertResult('failed', 'Must contain an info object');
            }
            else {
                var info = json.info;
                if (!info || !info.title) {
                    return new ConvertResult('failed', 'Must contain info.title');
                }
            }

            return new ConvertResult('passed', '');
        },

        setBasePath: function (json) {
            this.basePath = '';
            if (json.host) {
                this.basePath = json.host;
            }
            if (json.basePath) {
                this.basePath += json.basePath;
            }

            if (json.schemes && json.schemes.indexOf('https') != -1) {
                this.basePath = 'https://' + this.basePath;
            }
            else {
                this.basePath = 'http://' + this.basePath;
            }

            if (!this.endsWith(this.basePath, '/')) {
                this.basePath += '/';
            }
        },

        getFolderNameForPath: function (pathUrl) {
            if (pathUrl == '/') {
                return null;
            }
            var segments = pathUrl.split('/'),
                numSegments = segments.length,
                folderName = null;
            this.logger('Getting folder name for path: ' + pathUrl);
            this.logger('Segments: ' + JSON.stringify(segments));
            if (numSegments > 1) {
                folderName = segments[1];

                // create a folder for this path url
                if (!this.folders[folderName]) {
                    this.folders[folderName] = this.createNewFolder(folderName);
                }
                this.logger('For path ' + pathUrl + ', returning folderName ' + this.folders[folderName].name);
                return this.folders[folderName].name;
            }
            else {
                this.logger('Error - path MUST begin with /');
                return null;
            }
        },

        createNewFolder: function (name) {
            var newFolder = {
                'id': uuid.v4(),
                'name': name,
                'description': 'Folder for ' + name,
                'order': [],
                'collection_name': this.collectionJson.name,
                'collection_id': this.collectionId,
                'collection': this.collectionId
            };
            this.logger('Created folder ' + newFolder.name);
            return newFolder;
        },

        handleInfo: function (json) {
            this.collectionJson.name = json.info.title;
            this.collectionJson.description = json.info.description;
        },

        getParamsForPathItem: function (oldParams, newParams) {
            var retVal = {},
                numOldParams,
                numNewParams,
                i,
                parts,
                lastPart,
                getBaseParam;

            oldParams = oldParams || [];
            newParams = newParams || [];

            numOldParams = oldParams.length;
            numNewParams = newParams.length;

            for (i = 0; i < numOldParams; i++) {
                if (oldParams[i].$ref) {
                    // this is a ref
                    if (oldParams[i].$ref.indexOf('#/parameters') === 0) {
                        parts = oldParams[i].$ref.split('/');
                        lastPart = parts[parts.length - 1];
                        getBaseParam = this.baseParams[lastPart];
                        retVal[lastPart] = getBaseParam;
                    }
                }
                else {
                    retVal[oldParams[i].name] = oldParams[i];
                }
            }

            for (i = 0; i < numNewParams; i++) {
                if (newParams[i].$ref) {
                    // this is a ref
                    if (newParams[i].$ref.indexOf('#/parameters') === 0) {
                        parts = newParams[i].$ref.split('/');
                        lastPart = parts[parts.length - 1];
                        getBaseParam = this.baseParams[lastPart];
                        retVal[lastPart] = getBaseParam;
                    }
                }
                else {
                    retVal[newParams[i].name] = newParams[i];
                }
            }

            return retVal;
        },

        addOperationToFolder: function (path, method, operation, folderName, params) {
            var root = this,
                request = {
                    'id': uuid.v4(),
                    'headers': '',
                    'url': '',
                    'pathVariables': {},
                    'preRequestScript': '',
                    'method': 'GET',
                    'data': [],
                    'dataMode': 'params',
                    'description': operation.description || '',
                    'descriptionFormat': 'html',
                    'time': '',
                    'version': 2,
                    'responses': [],
                    'tests': '',
                    'collectionId': root.collectionId,
                    'synced': false
                },
                thisParams = this.getParamsForPathItem(params, operation.parameters),
                hasQueryParams = false,
                param,
                requestAttr,
                thisConsumes = root.globalConsumes;

            if (path.length > 0 && path[0] === '/') {
                path = path.substring(1);
            }
            request.url = decodeURI(url.resolve(this.basePath, path));
            request.method = method;
            request.name = operation.summary;
            request.time = (new Date()).getTime();

            // Handle custom swagger attributes for postman aws integration
            if (operation[META_KEY]) {
                for (requestAttr in operation[META_KEY]) {
                    if (operation[META_KEY].hasOwnProperty(requestAttr)) {
                        request[requestAttr] = operation[META_KEY][requestAttr];
                    }
                }
            }

            if (operation.consumes) {
                thisConsumes = operation.consumes;
            }
            // set the default dataMode for this request, even if it doesn't have a body
            // eg. for GET requests
            if (thisConsumes.indexOf('application/x-www-form-urlencoded') > -1) {
                request.dataMode = 'urlencoded';
            }

            // set data and headers
            for (param in thisParams) {
                if (thisParams.hasOwnProperty(param) && thisParams[param]) {
                    this.logger('Processing param: ' + JSON.stringify(param));
                    if (thisParams[param].in === 'query' && this.options.includeQueryParams !== false) {
                        if (!hasQueryParams) {
                            hasQueryParams = true;
                            request.url += '?';
                        }
                        request.url += thisParams[param].name + '={{' + thisParams[param].name + '}}&';
                    }

                    else if (thisParams[param].in === 'header') {
                        request.headers += thisParams[param].name + ': {{' + thisParams[param].name + '}}\n';
                    }

                    else if (thisParams[param].in === 'body') {
                        request.dataMode = 'raw';
                        request.data = thisParams[param].description;
                    }

                    else if (thisParams[param].in === 'formData') {
                        if (thisConsumes.indexOf('application/x-www-form-urlencoded') > -1) {
                            request.dataMode = 'urlencoded';
                        }
                        else {
                            request.dataMode = 'params';
                        }
                        request.data.push({
                            'key': thisParams[param].name,
                            'value': '{{' + thisParams[param].name + '}}',
                            'type': 'text',
                            'enabled': true
                        });
                    } // (thisParams[param].in === 'path') case not handled
                }
            }

            if (hasQueryParams && this.endsWith(request.url, '&')) {
                request.url = request.url.slice(0, -1);
            }

            this.collectionJson.requests.push(request);
            if (folderName !== null) {
                this.folders[folderName].order.push(request.id);
            }
            else {
                this.collectionJson.order.push(request.id);
            }
        },

        addPathItemToFolder: function (path, pathItem, folderName) {
            if (pathItem.$ref) {
                this.logger('Error - cannot handle $ref attributes');
                return;
            }

            var paramsForPathItem = this.getParamsForPathItem(this.baseParams, pathItem.parameters),
                acceptedPostmanVerbs = [
                    'get', 'put', 'post', 'patch', 'delete', 'copy', 'head', 'options',
                    'link', 'unlink', 'purge', 'lock', 'unlock', 'propfind', 'view'],
                numVerbs = acceptedPostmanVerbs.length,
                i,
                verb;

            // replace path variables {petId} with {{..}}
            if (path) {
                path = path.replace('{', '{{').replace('}', '}}');
            }

            for (i = 0; i < numVerbs; i++) {
                verb = acceptedPostmanVerbs[i];
                if (pathItem[verb]) {
                    this.addOperationToFolder(
                        path,
                        verb.toUpperCase(),
                        pathItem[verb],
                        folderName,
                        paramsForPathItem
                    );
                }
            }
        },

        handlePaths: function (json) {
            var paths = json.paths,
                path,
                folderName;

            // Add a folder for each path
            for (path in paths) {
                if (paths.hasOwnProperty(path)) {
                    folderName = this.getFolderNameForPath(path);
                    this.logger('Adding path item. path = ' + path + '   folder = ' + folderName);
                    this.addPathItemToFolder(path, paths[path], folderName);
                }
            }
        },

        handleParams: function (params, level) {
            if (!params) {
                return;
            }
            if (level === 'collection') {
                // base params
                for (var param in params) {
                    if (params.hasOwnProperty(param)) {
                        this.logger('Adding collection param: ' + param);
                        this.baseParams[param] = params[param];
                    }
                }
            }
        },

        addFoldersToCollection: function () {
            var folderName;
            for (folderName in this.folders) {
                if (this.folders.hasOwnProperty(folderName)) {
                    this.collectionJson.folders.push(this.folders[folderName]);
                }
            }
        },

        convert: function (json) {
            var validationResult = this.validate(json);
            if (validationResult.status === 'failed') {
                // error
                return validationResult;
            }

            this.collectionId = uuid.v4();

            this.globalConsumes = json.consumes || [];

            this.handleParams(json.parameters, 'collection');

            this.handleInfo(json);

            this.setBasePath(json);

            this.handlePaths(json);

            this.addFoldersToCollection();

            this.collectionJson.id = this.collectionId;
            // this.logger(JSON.stringify(this.collectionJson));
            this.logger('Swagger converted successfully');

            validationResult.collection = this.collectionJson;

            return validationResult;
        },

        // since travis doesnt support es6
        endsWith: function (str, suffix) {
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        }
    });

module.exports = Swagger2Postman;
<|endoftext|>


<commit_before>module.exports = require("./../../_gen/openfl/utils/AssetLibrary");

// TODO: Put elsewhere?
var internal = {
	SWFLiteLibrary: require ("../../_gen/openfl/_internal/swf/SWFLiteLibrary").default,
	BitmapSymbol: require ("../../_gen/openfl/_internal/symbols/BitmapSymbol").default,
	ButtonSymbol: require ("../../_gen/openfl/_internal/symbols/ButtonSymbol").default,
	DynamicTextSymbol: require ("../../_gen/openfl/_internal/symbols/DynamicTextSymbol").default,
	FontSymbol: require ("../../_gen/openfl/_internal/symbols/FontSymbol").default,
	ShapeSymbol: require ("../../_gen/openfl/_internal/symbols/ShapeSymbol").default,
	SpriteSymbol: require ("../../_gen/openfl/_internal/symbols/SpriteSymbol").default,
	StaticTextRecord: require ("../../_gen/openfl/_internal/symbols/StaticTextRecord").default,
	StaticTextSymbol: require ("../../_gen/openfl/_internal/symbols/StaticTextSymbol").default,
	SWFSymbol: require ("../../_gen/openfl/_internal/symbols/SWFSymbol").default,
	Frame: require ("../../_gen/openfl/_internal/timeline/Frame").default,
	FrameObject: require ("../../_gen/openfl/_internal/timeline/FrameObject").default,
	FrameObjectType: require ("../../_gen/openfl/_internal/timeline/FrameObjectType").default
}
module.exports._internal = internal;<commit_msg>Fix shapes in SWF assets on NPM<commit_after>module.exports = require("./../../_gen/openfl/utils/AssetLibrary");

// TODO: Put elsewhere?
var internal = {
	FilterType: require ("../../_gen/openfl/_internal/swf/FilterType").default,
	ShapeCommand: require ("../../_gen/openfl/_internal/swf/ShapeCommand").default,
	SWFLiteLibrary: require ("../../_gen/openfl/_internal/swf/SWFLiteLibrary").default,
	BitmapSymbol: require ("../../_gen/openfl/_internal/symbols/BitmapSymbol").default,
	ButtonSymbol: require ("../../_gen/openfl/_internal/symbols/ButtonSymbol").default,
	DynamicTextSymbol: require ("../../_gen/openfl/_internal/symbols/DynamicTextSymbol").default,
	FontSymbol: require ("../../_gen/openfl/_internal/symbols/FontSymbol").default,
	ShapeSymbol: require ("../../_gen/openfl/_internal/symbols/ShapeSymbol").default,
	SpriteSymbol: require ("../../_gen/openfl/_internal/symbols/SpriteSymbol").default,
	StaticTextRecord: require ("../../_gen/openfl/_internal/symbols/StaticTextRecord").default,
	StaticTextSymbol: require ("../../_gen/openfl/_internal/symbols/StaticTextSymbol").default,
	SWFSymbol: require ("../../_gen/openfl/_internal/symbols/SWFSymbol").default,
	Frame: require ("../../_gen/openfl/_internal/timeline/Frame").default,
	FrameObject: require ("../../_gen/openfl/_internal/timeline/FrameObject").default,
	FrameObjectType: require ("../../_gen/openfl/_internal/timeline/FrameObjectType").default
}
module.exports._internal = internal;<|endoftext|>


<commit_before>Posts = new Mongo.Collection('posts');

Posts.allow({
  update: function(userId, post) {
    return ownsDocument(userId, post);
  },
  remove: function(userId, post) {
    return ownsDocument(userId, post);
  }
});

Posts.deny({
  update: function(userId, post, fieldNames) {
    return (_.without(fieldNames, 'url', 'title').length > 0);
  }
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String
    });

    var postWithSameLink = Posts.findOne({ url: postAttributes.url });

    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      };
    }

    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });

    var postId = Posts.insert(post);

    return {
      _id: postId
    };
  },

  postUpdate: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String,
      _id: String
    });

    var postWithSameLink = Posts.findOne({ url: postAttributes.url });

    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      };
    }

    var postId = Post.update(postAttributes._id, {$set: postProperties});

  }
});

validatePost = function(post) {
  var errors = {};

  if (!post.title) {
    errors.title = "Please fill in a headline";
  }

  if (!post.url) {
    errors.url = "Please fill in a URL";
  }

  return errors;
}
<commit_msg>Add post submission server side validations<commit_after>Posts = new Mongo.Collection('posts');

Posts.allow({
  update: function(userId, post) {
    return ownsDocument(userId, post);
  },
  remove: function(userId, post) {
    return ownsDocument(userId, post);
  }
});

Posts.deny({
  update: function(userId, post, fieldNames) {
    return (_.without(fieldNames, 'url', 'title').length > 0);
  }
});

Meteor.methods({
  postInsert: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String
    });

    var errors = validatePost(postAttributes);
    if (errors.title || errors.url) {
      throw new Meteor.Error('invalid-post', 'You must set a title and URL to your post');
    }

    var postWithSameLink = Posts.findOne({ url: postAttributes.url });

    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      };
    }

    var user = Meteor.user();
    var post = _.extend(postAttributes, {
      userId: user._id,
      author: user.username,
      submitted: new Date()
    });

    var postId = Posts.insert(post);

    return {
      _id: postId
    };
  },

  postUpdate: function(postAttributes) {
    check(Meteor.userId(), String);
    check(postAttributes, {
      title: String,
      url: String,
      _id: String
    });

    var postWithSameLink = Posts.findOne({ url: postAttributes.url });

    if (postWithSameLink) {
      return {
        postExists: true,
        _id: postWithSameLink._id
      };
    }

    var postId = Post.update(postAttributes._id, {$set: postProperties});

  }
});

validatePost = function(post) {
  var errors = {};

  if (!post.title) {
    errors.title = "Please fill in a headline";
  }

  if (!post.url) {
    errors.url = "Please fill in a URL";
  }

  return errors;
}
<|endoftext|>


<commit_before>'use strict';

const assert = require('./../../assert');
const common = require('./../../common');

let battle;

describe('Neutralizing Gas', function () {
	afterEach(function () {
		battle.destroy();
	});

	it('should prevent switch-in abilities from activating', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Gyarados", ability: 'intimidate', moves: ['splash']}]});
		battle.setPlayer('p2', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['toxicspikes']}]});
		assert.statStage(battle.p2.active[0], 'atk', 0);
	});

	it('should ignore damage-reducing abilities', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', item: 'expertbelt', moves: ['sludgebomb']}]});
		battle.setPlayer('p2', {team: [{species: "Mr. Mime", ability: 'filter', item: 'laggingtail', moves: ['substitute']}]});
		battle.makeChoices('move sludgebomb', 'move substitute');
		assert(!battle.p1.active[0].volatiles['substitute']);
	});

	it('should negate self-healing abilities', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['toxic']}]});
		battle.setPlayer('p2', {team: [{species: "Breloom", ability: 'poisonheal', moves: ['swordsdance']}]});
		battle.makeChoices('move toxic', 'move swordsdance');
		assert.false.fullHP(battle.p2.active[0]);
	});

	it('should negate abilities that suppress item effects', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['reflect']}]});
		battle.setPlayer('p2', {team: [{species: "Reuniclus", ability: 'magicguard', item: 'lifeorb', moves: ['shadowball']}]});
		battle.makeChoices('move reflect', 'move shadowball');
		assert.false.fullHP(battle.p2.active[0]);
	});

	it('should negate abilities that modify boosts', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['spore']}]});
		battle.setPlayer('p2', {team: [{species: "Shuckle", ability: 'contrary', moves: ['sleeptalk', 'superpower']}]});
		battle.makeChoices('move spore', 'move sleeptalk');
		assert.statStage(battle.p2.active[0], 'atk', -1);
	});

	it(`should negate abilites that activate on switch-out`, function () {
		battle = common.createBattle([
			[{species: "Weezing", ability: 'neutralizinggas', moves: ['toxic']},
				{species: "Type: Null", ability: 'battlearmor', moves: ['facade']}],
			[{species: "Corsola", ability: 'naturalcure', moves: ['uturn']},
				{species: "Magikarp", ability: 'rattled', moves: ['splash']}],
		]);
		battle.makeChoices('move toxic', 'move uturn');
		battle.makeChoices('', 'switch 2');
		battle.makeChoices('switch 2', 'switch 2');
		assert.equal(battle.p2.active[0].status, 'tox');
	});

	it('should negate abilities that modify move type', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Gengar", ability: 'neutralizinggas', moves: ['laserfocus']}]});
		battle.setPlayer('p2', {team: [{species: "Sylveon", ability: 'pixilate', moves: ['hypervoice']}]});
		battle.makeChoices('move laserfocus', 'move hypervoice');
		assert.fullHP(battle.p1.active[0]);
	});

	it("should negate abilities that damage the attacker", function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [
			{species: 'Weezing-Galar', ability: 'neutralizinggas', moves: ['payback']},
		]});
		battle.setPlayer('p2', {team: [
			{species: 'Ferrothorn', ability: 'ironbarbs', moves: ['rockpolish']},
		]});
		battle.makeChoices();
		assert.fullHP(battle.p1.active[0]);
	});

	it('should not activate if Neutralizing Gas leaves the field', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [
			{species: "Weezing", ability: 'neutralizinggas', moves: ['snore']},
			{species: "Greninja", ability: 'torrent', moves: ['teleport']},
		]});
		battle.setPlayer('p2', {team: [
			{species: "Ditto", ability: 'imposter', moves: ['sleeptalk']},
		]});
		assert.notEqual(battle.p1.active[0].species, battle.p2.active[0].species);
		battle.makeChoices('switch greninja', 'move sleeptalk');
		assert.notEqual(battle.p1.active[0].species, battle.p2.active[0].species);
		assert.notEqual(battle.p1.pokemon[1].species, battle.p2.active[0].species);
	});

	it(`should prevent Unburden's activation when it is active on the field`, function () {
		battle = common.createBattle([[
			{species: "Wynaut", ability: 'unburden', item: 'sitrusberry', evs: {hp: 4}, moves: ['bellydrum']},
		], [
			{species: "Pancham", ability: 'neutralizinggas', moves: ['sleeptalk']},
			{species: "Whismur", moves: ['sleeptalk']},
		]]);

		const wynaut = battle.p1.active[0];
		const originalSpeed = wynaut.getStat('spe');
		battle.makeChoices();
		assert.equal(wynaut.getStat('spe'), originalSpeed);

		//The chance to trigger Unburden is gone, so it missed the timing and doesn't gain the speed post-NGas removal
		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.getStat('spe'), originalSpeed);
	});

	it.skip(`should negate Unburden when Neutralizing Gas enters the field`, function () {
		battle = common.createBattle([[
			{species: "Wynaut", ability: 'unburden', item: 'sitrusberry', evs: {hp: 4}, moves: ['bellydrum']},
		], [
			{species: "Whismur", moves: ['sleeptalk']},
			{species: "Pancham", ability: 'neutralizinggas', moves: ['sleeptalk']},
		]]);

		const wynaut = battle.p1.active[0];
		const originalSpeed = wynaut.getStat('spe');
		battle.makeChoices();
		assert.equal(wynaut.getStat('spe'), originalSpeed * 2);

		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.getStat('spe'), originalSpeed);

		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.getStat('spe'), originalSpeed * 2);
	});

	it.skip(`should cause Illusion to instantly wear off when Neutralizing Gas enters the field`, function () {
		battle = common.createBattle([[
			{species: "Zoroark", ability: 'illusion', moves: ['sleeptalk']},
			{species: "Eternatus", moves: ['sleeptalk']},
		], [
			{species: "Wynaut", moves: ['sleeptalk']},
			{species: "Weezing", ability: 'neutralizinggas', moves: ['sleeptalk']},
		]]);

		battle.makeChoices('auto', 'switch 2');
		assert(battle.log.some(line => line.includes('|-end|p1a: Zoroark|Illusion')));
	});

	it.skip(`should cause Slow Start to instantly wear off/restart when Neutralizing Gas leaves/enters the field`, function () {
		battle = common.createBattle([[
			{species: "Regigigas", ability: 'slowstart', moves: ['sleeptalk']},
			{species: "Eternatus", moves: ['sleeptalk']},
		], [
			{species: "Wynaut", moves: ['sleeptalk']},
			{species: "Weezing", ability: 'neutralizinggas', moves: ['sleeptalk']},
		]]);

		const regigigas = battle.p1.active[0];
		const slowStartSpeed = regigigas.getStat('spe');

		//Slow Start should be negated, so it should have its original, non-Slow Start speed
		battle.makeChoices('auto', 'switch 2');
		assert.equal(regigigas.getStat('spe'), slowStartSpeed * 2);

		//Slow Start should be turned back on, so it should have its Slow Start speed again
		battle.makeChoices('auto', 'switch 2');
		assert.equal(regigigas.getStat('spe'), slowStartSpeed);
	});

	it.skip(`should not cause Gluttony to instantly eat Berries when Neutralizing Gas leaves the field`, function () {
		battle = common.createBattle([[
			{species: "Wynaut", ability: 'gluttony', item: 'aguavberry', evs: {hp: 4}, moves: ['bellydrum']},
		], [
			{species: "Pancham", ability: 'neutralizinggas', moves: ['sleeptalk']},
			{species: "Whismur", level: 1, moves: ['seismictoss']},
		]]);

		const wynaut = battle.p1.active[0];
		battle.makeChoices();
		assert.equal(wynaut.hp, Math.floor(wynaut.maxhp / 2));

		// Gluttony doesn't activate because it missed the timing
		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.hp, Math.floor(wynaut.maxhp / 2));

		// Gluttony now has the opportunity to activate the Aguav Berry again on taking damage
		battle.makeChoices();
		assert.equal(wynaut.hp, Math.floor(wynaut.maxhp / 2) - 1 + Math.floor(wynaut.maxhp * 0.33));
	});

	it.skip(`should not trigger twice if negated then replaced`, function () {
		battle = common.createBattle([[
			{species: "Weezing", ability: 'neutralizinggas', moves: ['sleeptalk']},
		], [
			{species: "Wynaut", ability: 'intrepidsword', moves: ['gastroacid', 'simplebeam']},
		]]);

		const wynaut = battle.p2.active[0];
		battle.makeChoices();
		assert.statStage(wynaut, 'atk', 1);

		// We already negated NGas, so it shouldn't run other abilities again
		battle.makeChoices('auto', 'move simplebeam');
		assert.statStage(wynaut, 'atk', 1);
	});
});
<commit_msg>Clarify Neutralizing Gas + Imposter test<commit_after>'use strict';

const assert = require('./../../assert');
const common = require('./../../common');

let battle;

describe('Neutralizing Gas', function () {
	afterEach(function () {
		battle.destroy();
	});

	it('should prevent switch-in abilities from activating', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Gyarados", ability: 'intimidate', moves: ['splash']}]});
		battle.setPlayer('p2', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['toxicspikes']}]});
		assert.statStage(battle.p2.active[0], 'atk', 0);
	});

	it('should ignore damage-reducing abilities', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', item: 'expertbelt', moves: ['sludgebomb']}]});
		battle.setPlayer('p2', {team: [{species: "Mr. Mime", ability: 'filter', item: 'laggingtail', moves: ['substitute']}]});
		battle.makeChoices('move sludgebomb', 'move substitute');
		assert(!battle.p1.active[0].volatiles['substitute']);
	});

	it('should negate self-healing abilities', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['toxic']}]});
		battle.setPlayer('p2', {team: [{species: "Breloom", ability: 'poisonheal', moves: ['swordsdance']}]});
		battle.makeChoices('move toxic', 'move swordsdance');
		assert.false.fullHP(battle.p2.active[0]);
	});

	it('should negate abilities that suppress item effects', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['reflect']}]});
		battle.setPlayer('p2', {team: [{species: "Reuniclus", ability: 'magicguard', item: 'lifeorb', moves: ['shadowball']}]});
		battle.makeChoices('move reflect', 'move shadowball');
		assert.false.fullHP(battle.p2.active[0]);
	});

	it('should negate abilities that modify boosts', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Weezing", ability: 'neutralizinggas', moves: ['spore']}]});
		battle.setPlayer('p2', {team: [{species: "Shuckle", ability: 'contrary', moves: ['sleeptalk', 'superpower']}]});
		battle.makeChoices('move spore', 'move sleeptalk');
		assert.statStage(battle.p2.active[0], 'atk', -1);
	});

	it(`should negate abilites that activate on switch-out`, function () {
		battle = common.createBattle([
			[{species: "Weezing", ability: 'neutralizinggas', moves: ['toxic']},
				{species: "Type: Null", ability: 'battlearmor', moves: ['facade']}],
			[{species: "Corsola", ability: 'naturalcure', moves: ['uturn']},
				{species: "Magikarp", ability: 'rattled', moves: ['splash']}],
		]);
		battle.makeChoices('move toxic', 'move uturn');
		battle.makeChoices('', 'switch 2');
		battle.makeChoices('switch 2', 'switch 2');
		assert.equal(battle.p2.active[0].status, 'tox');
	});

	it('should negate abilities that modify move type', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [{species: "Gengar", ability: 'neutralizinggas', moves: ['laserfocus']}]});
		battle.setPlayer('p2', {team: [{species: "Sylveon", ability: 'pixilate', moves: ['hypervoice']}]});
		battle.makeChoices('move laserfocus', 'move hypervoice');
		assert.fullHP(battle.p1.active[0]);
	});

	it("should negate abilities that damage the attacker", function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [
			{species: 'Weezing-Galar', ability: 'neutralizinggas', moves: ['payback']},
		]});
		battle.setPlayer('p2', {team: [
			{species: 'Ferrothorn', ability: 'ironbarbs', moves: ['rockpolish']},
		]});
		battle.makeChoices();
		assert.fullHP(battle.p1.active[0]);
	});

	it('should not activate Imposter if Neutralizing Gas leaves the field', function () {
		battle = common.createBattle();
		battle.setPlayer('p1', {team: [
			{species: "Weezing", ability: 'neutralizinggas', moves: ['snore']},
			{species: "Greninja", ability: 'torrent', moves: ['teleport']},
		]});
		battle.setPlayer('p2', {team: [
			{species: "Ditto", ability: 'imposter', moves: ['sleeptalk']},
		]});
		assert.notEqual(battle.p1.active[0].species, battle.p2.active[0].species);
		battle.makeChoices('switch greninja', 'move sleeptalk');
		assert.notEqual(battle.p1.active[0].species, battle.p2.active[0].species);
		assert.notEqual(battle.p1.pokemon[1].species, battle.p2.active[0].species);
	});

	it(`should prevent Unburden's activation when it is active on the field`, function () {
		battle = common.createBattle([[
			{species: "Wynaut", ability: 'unburden', item: 'sitrusberry', evs: {hp: 4}, moves: ['bellydrum']},
		], [
			{species: "Pancham", ability: 'neutralizinggas', moves: ['sleeptalk']},
			{species: "Whismur", moves: ['sleeptalk']},
		]]);

		const wynaut = battle.p1.active[0];
		const originalSpeed = wynaut.getStat('spe');
		battle.makeChoices();
		assert.equal(wynaut.getStat('spe'), originalSpeed);

		//The chance to trigger Unburden is gone, so it missed the timing and doesn't gain the speed post-NGas removal
		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.getStat('spe'), originalSpeed);
	});

	it.skip(`should negate Unburden when Neutralizing Gas enters the field`, function () {
		battle = common.createBattle([[
			{species: "Wynaut", ability: 'unburden', item: 'sitrusberry', evs: {hp: 4}, moves: ['bellydrum']},
		], [
			{species: "Whismur", moves: ['sleeptalk']},
			{species: "Pancham", ability: 'neutralizinggas', moves: ['sleeptalk']},
		]]);

		const wynaut = battle.p1.active[0];
		const originalSpeed = wynaut.getStat('spe');
		battle.makeChoices();
		assert.equal(wynaut.getStat('spe'), originalSpeed * 2);

		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.getStat('spe'), originalSpeed);

		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.getStat('spe'), originalSpeed * 2);
	});

	it.skip(`should cause Illusion to instantly wear off when Neutralizing Gas enters the field`, function () {
		battle = common.createBattle([[
			{species: "Zoroark", ability: 'illusion', moves: ['sleeptalk']},
			{species: "Eternatus", moves: ['sleeptalk']},
		], [
			{species: "Wynaut", moves: ['sleeptalk']},
			{species: "Weezing", ability: 'neutralizinggas', moves: ['sleeptalk']},
		]]);

		battle.makeChoices('auto', 'switch 2');
		assert(battle.log.some(line => line.includes('|-end|p1a: Zoroark|Illusion')));
	});

	it.skip(`should cause Slow Start to instantly wear off/restart when Neutralizing Gas leaves/enters the field`, function () {
		battle = common.createBattle([[
			{species: "Regigigas", ability: 'slowstart', moves: ['sleeptalk']},
			{species: "Eternatus", moves: ['sleeptalk']},
		], [
			{species: "Wynaut", moves: ['sleeptalk']},
			{species: "Weezing", ability: 'neutralizinggas', moves: ['sleeptalk']},
		]]);

		const regigigas = battle.p1.active[0];
		const slowStartSpeed = regigigas.getStat('spe');

		// Slow Start should be negated, so it should have its original, non-Slow Start speed
		battle.makeChoices('auto', 'switch 2');
		assert.equal(regigigas.getStat('spe'), slowStartSpeed * 2);

		// Slow Start should be turned back on, so it should have its Slow Start speed again
		battle.makeChoices('auto', 'switch 2');
		assert.equal(regigigas.getStat('spe'), slowStartSpeed);
	});

	it.skip(`should not cause Gluttony to instantly eat Berries when Neutralizing Gas leaves the field`, function () {
		battle = common.createBattle([[
			{species: "Wynaut", ability: 'gluttony', item: 'aguavberry', evs: {hp: 4}, moves: ['bellydrum']},
		], [
			{species: "Pancham", ability: 'neutralizinggas', moves: ['sleeptalk']},
			{species: "Whismur", level: 1, moves: ['seismictoss']},
		]]);

		const wynaut = battle.p1.active[0];
		battle.makeChoices();
		assert.equal(wynaut.hp, Math.floor(wynaut.maxhp / 2));

		// Gluttony doesn't activate because it missed the timing
		battle.makeChoices('auto', 'switch 2');
		assert.equal(wynaut.hp, Math.floor(wynaut.maxhp / 2));

		// Gluttony now has the opportunity to activate the Aguav Berry again on taking damage
		battle.makeChoices();
		assert.equal(wynaut.hp, Math.floor(wynaut.maxhp / 2) - 1 + Math.floor(wynaut.maxhp * 0.33));
	});

	it.skip(`should not trigger twice if negated then replaced`, function () {
		battle = common.createBattle([[
			{species: "Weezing", ability: 'neutralizinggas', moves: ['sleeptalk']},
		], [
			{species: "Wynaut", ability: 'intrepidsword', moves: ['gastroacid', 'simplebeam']},
		]]);

		const wynaut = battle.p2.active[0];
		battle.makeChoices();
		assert.statStage(wynaut, 'atk', 1);

		// We already negated NGas, so it shouldn't run other abilities again
		battle.makeChoices('auto', 'move simplebeam');
		assert.statStage(wynaut, 'atk', 1);
	});
});
<|endoftext|>


<commit_before>/**
 * Wake Up Platform
 * (c) Telefonica Digital, 2014 - All rights reserved
 * License: GNU Affero V3 (see LICENSE file)
 * Fernando Rodríguez Sela <frsela at tid dot es>
 * Guillermo López Leal <gll at tid dot es>
 */

'use strict';

var request = require('request'),
    net = require('net'),
    config = process.configuration,
    log = require('../shared_libs/logger.js'),
    helpers = require('../shared_libs/helpers.js');

var mn = function mobileNetwork(networksPath) {
    var networks = require(networksPath);

    var checkWakeup = function(URL, callback) {
        log.debug('Checking ' + URL);
        var options = {
            url: URL,
            // We need to fake this for the local wakeup to
            // accept our query
            headers: {
                'x-client-cert-verified': 'SUCCESS',
                'x-client-cert-dn': 'Wakeup_checker'
            }
        };
        // Callback with true/false (online/offline) and the trackingID
        // if it is set to trace between wakeups
        request(options, function(error, response/*, body*/) {
            if (!error && response.statusCode === 200) {
                log.debug(URL + ' success');
                callback(true, response.headers['x-tracking-id']);
            } else {
                log.debug(URL + ' failed');
                callback(false, (response && response.headers &&
                   response.headers['x-tracking-id'])
                );
            }
        });
    };

    var checkNetworks = function() {
        log.debug('checkNetworks() + ' + JSON.stringify(networks));
        var keys = Object.keys(networks);
        keys.forEach(function(id) {
            if (networks[id].host) {
                var toCheck = networks[id].host + '/about';
                checkWakeup(toCheck, function(online, trackingID) {
                    var on = online ? enableNetwork(id) : disableNetwork(id);
                    log.info(Date.now() + ' -- ' + trackingID +
                        ' -- wakeup_check -- ' + id + ' -- ' + networks[id].host +
                        ' -- ' + (on ? 'OK' : 'KO'));
                });
            }
        });
    };

    checkNetworks();
    setInterval(checkNetworks, config.checkInterval);

    function getNetwork(netid) {
        var res = networks[netid];
        if (!res) {
            return null;
        }
        return res;
    }

    function getAllNetworks() {
        return networks;
    }

    function enableNetwork(networkName) {
        log.debug('Enabling network ' + networkName);
        var net = getNetwork(networkName);
        if (net) {
            networks[networkName].offline = false;
        }
        return !networks[networkName].offline;
    }

    function disableNetwork(networkName) {
        log.debug('Disabling network ' + networkName);
        var net = getNetwork(networkName);
        if (net) {
            networks[networkName].offline = true;
        }
        return !networks[networkName].offline;
    }

    return {
        getNetworkIDForMCCMNC: function(mcc, mnc) {
            return mcc + '-' + mnc;
        },

        // Checks if the deviceip is in a valid range for the specified network
        getNetworkForIP: function(netid, deviceip) {
            if (!net.isIP(deviceip)) {
                return { error: 'No valid device IP', code: 400 };
            }

            var network = getNetwork(netid);
            if (!network) {
                return { error: 'No network found', code: 404 };
            }

            // Client IP is out of the mobile network
            if (!helpers.isIPInNetwork(deviceip, network.range)) {
                return {
                    error: 'Client IP (' + deviceip +
                        ') is out of the mobile network range - ' + network.range,
                    code: 400
                };
            }

            return network;
        },

        // Returns an array with all networks with a local node in them
        getAllNetworks: function() {
            return getAllNetworks();
        },

        // Enable/Disable network status
        changeNetworkStatus: function(networkName, networkStatus) {
            if (networkStatus) {
                enableNetwork(networkName);
            } else {
                disableNetwork(networkName);
            }
        }
    };
};

module.exports = function(networksPath) {
    return mn(networksPath);
};
<commit_msg>Local nodes check should be done with the Status router instead the About one<commit_after>/**
 * Wake Up Platform
 * (c) Telefonica Digital, 2014 - All rights reserved
 * License: GNU Affero V3 (see LICENSE file)
 * Fernando Rodríguez Sela <frsela at tid dot es>
 * Guillermo López Leal <gll at tid dot es>
 */

'use strict';

var request = require('request'),
    net = require('net'),
    config = process.configuration,
    log = require('../shared_libs/logger.js'),
    helpers = require('../shared_libs/helpers.js');

var mn = function mobileNetwork(networksPath) {
    var networks = require(networksPath);

    var checkWakeup = function(URL, callback) {
        log.debug('Checking ' + URL);
        var options = {
            url: URL,
            // We need to fake this for the local wakeup to
            // accept our query
            headers: {
                'x-client-cert-verified': 'SUCCESS',
                'x-client-cert-dn': 'Wakeup_checker'
            }
        };
        // Callback with true/false (online/offline) and the trackingID
        // if it is set to trace between wakeups
        request(options, function(error, response/*, body*/) {
            if (!error && response.statusCode === 200) {
                log.debug(URL + ' success');
                callback(true, response.headers['x-tracking-id']);
            } else {
                log.debug(URL + ' failed');
                callback(false, (response && response.headers &&
                   response.headers['x-tracking-id'])
                );
            }
        });
    };

    var checkNetworks = function() {
        log.debug('checkNetworks() + ' + JSON.stringify(networks));
        var keys = Object.keys(networks);
        keys.forEach(function(id) {
            if (networks[id].host) {
                var toCheck = networks[id].host + '/status';
                checkWakeup(toCheck, function(online, trackingID) {
                    var on = online ? enableNetwork(id) : disableNetwork(id);
                    log.info(Date.now() + ' -- ' + trackingID +
                        ' -- wakeup_check -- ' + id + ' -- ' + networks[id].host +
                        ' -- ' + (on ? 'OK' : 'KO'));
                });
            }
        });
    };

    checkNetworks();
    setInterval(checkNetworks, config.checkInterval);

    function getNetwork(netid) {
        var res = networks[netid];
        if (!res) {
            return null;
        }
        return res;
    }

    function getAllNetworks() {
        return networks;
    }

    function enableNetwork(networkName) {
        log.debug('Enabling network ' + networkName);
        var net = getNetwork(networkName);
        if (net) {
            networks[networkName].offline = false;
        }
        return !networks[networkName].offline;
    }

    function disableNetwork(networkName) {
        log.debug('Disabling network ' + networkName);
        var net = getNetwork(networkName);
        if (net) {
            networks[networkName].offline = true;
        }
        return !networks[networkName].offline;
    }

    return {
        getNetworkIDForMCCMNC: function(mcc, mnc) {
            return mcc + '-' + mnc;
        },

        // Checks if the deviceip is in a valid range for the specified network
        getNetworkForIP: function(netid, deviceip) {
            if (!net.isIP(deviceip)) {
                return { error: 'No valid device IP', code: 400 };
            }

            var network = getNetwork(netid);
            if (!network) {
                return { error: 'No network found', code: 404 };
            }

            // Client IP is out of the mobile network
            if (!helpers.isIPInNetwork(deviceip, network.range)) {
                return {
                    error: 'Client IP (' + deviceip +
                        ') is out of the mobile network range - ' + network.range,
                    code: 400
                };
            }

            return network;
        },

        // Returns an array with all networks with a local node in them
        getAllNetworks: function() {
            return getAllNetworks();
        },

        // Enable/Disable network status
        changeNetworkStatus: function(networkName, networkStatus) {
            if (networkStatus) {
                enableNetwork(networkName);
            } else {
                disableNetwork(networkName);
            }
        }
    };
};

module.exports = function(networksPath) {
    return mn(networksPath);
};
<|endoftext|>


<commit_before>odoo.define('website_slides.tour.slide.course.publisher', function (require) {
'use strict';

var tour = require('web_tour.tour');
var slidesTourTools = require('website_slides.tour.tools');

/**
 * Global use case:
 * a user (website publisher) creates a course;
 * he updates it;
 * he creates some lessons in it;
 * he publishes it;
 */
tour.register('course_publisher', {
    url: '/slides',
    test: true
}, [{
    content: 'eLearning: click on New (top-menu)',
    trigger: 'li.o_new_content_menu a'
}, {
    content: 'eLearning: click on New Course',
    trigger: 'a:contains("New Course")'
}, {
    content: 'eLearning: set name',
    trigger: 'input[name="name"]',
    run: 'text How to Déboulonnate',
}, {
    content: 'eLearning: click on tags',
    trigger: 'ul.select2-choices:first',
}, {
    content: 'eLearning: select gardener tag',
    trigger: 'div.select2-result-label:contains("Gardener")',
    in_modal: false,
}, {
    content: 'eLearning: set description',
    trigger: 'textarea[name="description"]',
    run: 'text Déboulonnate is very common at Fleurus',
}, {
    content: 'eLearning: we want reviews',
    trigger: 'input[name="allow_comment"]',
}, {
    content: 'eLearning: seems cool, create it',
    trigger: 'button:contains("Create")',
}, {
    content: 'eLearning: launch course edition',
    trigger: 'li[id="edit-page-menu"] a',
}, {
    content: 'eLearning: double click image to edit it',
    trigger: 'img.o_wslides_course_pict',
    run: 'dblclick',
}, {
    content: 'eLearning: click pâtissière',
    trigger: 'img[title="sell.jpg"]',
}, {
    content: 'eLearning: validate pâtissière',
    trigger: 'footer.modal-footer button:contains("Add")',
}, {
    content: 'eLearning: is the pâtissière set ?',
    trigger: 'img.o_wslides_course_pict',
    run: function () {
        if ($('img.o_wslides_course_pict').attr('src').endsWith('sell.jpg')) {
            $('img.o_wslides_course_pict').addClass('o_wslides_tour_success');
        }
    },
}, {
    content: 'eLearning: the pâtissière is set !',
    trigger: 'img.o_wslides_course_pict.o_wslides_tour_success',
}, {
    content: 'eLearning: save course edition',
    trigger: 'button[data-action="save"]',
}, {
    content: 'eLearning: course create with current member',
    extra_trigger: 'body:not(.editor_enable)',  // wait for editor to close
    trigger: '.o_wslides_js_course_join:contains("You\'re enrolled")',
    run: function () {} // check membership
}
].concat(
    slidesTourTools.addSection('Introduction'),
    slidesTourTools.addVideoToSection('Introduction'),
    [{
    content: 'eLearning: publish newly added course',
    trigger: 'span:contains("Dschinghis Khan - Moskau 1979")',  // wait for slide to appear
    // trigger: 'span.o_wslides_js_slide_toggle_is_preview:first',
    run: function () {
        $('span.o_wslides_js_slide_toggle_is_preview:first').click();
    }
}]
//     [
// {
//     content: 'eLearning: move new course inside introduction',
//     trigger: 'div.o_wslides_slides_list_drag',
//     // run: 'drag_and_drop div.o_wslides_slides_list_drag ul.ui-sortable:first',
//     run: 'drag_and_drop div.o_wslides_slides_list_drag a.o_wslides_js_slide_section_add',
// }]
));

});
<commit_msg>[FIX] website_slides: external tour used old code<commit_after>odoo.define('website_slides.tour.slide.course.publisher', function (require) {
'use strict';

var tour = require('web_tour.tour');
var slidesTourTools = require('website_slides.tour.tools');

/**
 * Global use case:
 * a user (website publisher) creates a course;
 * he updates it;
 * he creates some lessons in it;
 * he publishes it;
 */
tour.register('course_publisher', {
    url: '/slides',
    test: true
}, [{
    content: 'eLearning: click on New (top-menu)',
    trigger: 'li.o_new_content_menu a'
}, {
    content: 'eLearning: click on New Course',
    trigger: 'a:contains("New Course")'
}, {
    content: 'eLearning: set name',
    trigger: 'input[name="name"]',
    run: 'text How to Déboulonnate',
}, {
    content: 'eLearning: click on tags',
    trigger: 'ul.select2-choices:first',
}, {
    content: 'eLearning: select gardener tag',
    trigger: 'div.select2-result-label:contains("Gardener")',
    in_modal: false,
}, {
    content: 'eLearning: set description',
    trigger: 'input[name="description"]',
    run: 'text Déboulonnate is very common at Fleurus',
}, {
    content: 'eLearning: we want reviews',
    trigger: 'input[name="allow_comment"]',
}, {
    content: 'eLearning: seems cool, create it',
    trigger: 'button:contains("Create")',
}, {
    content: 'eLearning: launch course edition',
    trigger: 'li[id="edit-page-menu"] a',
}, {
    content: 'eLearning: double click image to edit it',
    trigger: 'img.o_wslides_course_pict',
    run: 'dblclick',
}, {
    content: 'eLearning: click pâtissière',
    trigger: 'img[title="sell.jpg"]',
}, {
    content: 'eLearning: validate pâtissière',
    trigger: 'footer.modal-footer button:contains("Add")',
}, {
    content: 'eLearning: is the pâtissière set ?',
    trigger: 'img.o_wslides_course_pict',
    run: function () {
        if ($('img.o_wslides_course_pict').attr('src').endsWith('sell.jpg')) {
            $('img.o_wslides_course_pict').addClass('o_wslides_tour_success');
        }
    },
}, {
    content: 'eLearning: the pâtissière is set !',
    trigger: 'img.o_wslides_course_pict.o_wslides_tour_success',
}, {
    content: 'eLearning: save course edition',
    trigger: 'button[data-action="save"]',
}, {
    content: 'eLearning: course create with current member',
    extra_trigger: 'body:not(.editor_enable)',  // wait for editor to close
    trigger: '.o_wslides_js_course_join:contains("You\'re enrolled")',
    run: function () {} // check membership
}
].concat(
    slidesTourTools.addSection('Introduction'),
    slidesTourTools.addVideoToSection('Introduction'),
    [{
    content: 'eLearning: publish newly added course',
    trigger: 'span:contains("Dschinghis Khan - Moskau 1979")',  // wait for slide to appear
    // trigger: 'span.o_wslides_js_slide_toggle_is_preview:first',
    run: function () {
        $('span.o_wslides_js_slide_toggle_is_preview:first').click();
    }
}]
//     [
// {
//     content: 'eLearning: move new course inside introduction',
//     trigger: 'div.o_wslides_slides_list_drag',
//     // run: 'drag_and_drop div.o_wslides_slides_list_drag ul.ui-sortable:first',
//     run: 'drag_and_drop div.o_wslides_slides_list_drag a.o_wslides_js_slide_section_add',
// }]
));

});
<|endoftext|>


<commit_before>Posts = new Mongo.Collection('posts');

Posts.allow({
    // User must be logged in to post
    insert: function (userId, doc) {
        return !! userId;
    }
});

Meteor.methods({
    postInsert: function (postAttributes) {
        /*
        Insert a post into the database
        checking attributes
        and adding user and date fields
        */

        // Check fields for safety
        check(Meteor.userId(), String);
        check(postAttributes, {
            title: String,
            url: String
        });

        // Get the current user
        var user = Meteor.user();

        // Extend the post object with user attributes and submssion date
        var post = _.extend(postAttributes, {
            userId: user._id,
            author: user.username,
            submitted: new Date()
        });

        // Insert the post
        var postId = Posts.insert(post);

        // Return ID of new post
        return {
            id: postId
        }
    }
});
<commit_msg>Make sure URL is unique<commit_after>Posts = new Mongo.Collection('posts');

Posts.allow({
    // User must be logged in to post
    insert: function (userId, doc) {
        return !! userId;
    }
});

Meteor.methods({
    postInsert: function (postAttributes) {
        /*
        Insert a post into the database
        checking attributes
        and adding user and date fields
        */

        // Check fields for safety
        check(Meteor.userId(), String);
        check(postAttributes, {
            title: String,
            url: String
        });

        // Make sure URL has not been submitted
        var postWithSameLink = Posts.findOne({url: postAttributes.url});
        if (postWithSameLink) {
            return {
                postExists: true,
                _id: postWith SameLink._id
            }
        }

        // Get the current user
        var user = Meteor.user();

        // Extend the post object with user attributes and submssion date
        var post = _.extend(postAttributes, {
            userId: user._id,
            author: user.username,
            submitted: new Date()
        });

        // Insert the post
        var postId = Posts.insert(post);

        // Return ID of new post
        return {
            id: postId
        }
    }
});
<|endoftext|>