<commit_before>/*
 * jQuery UI Slider @VERSION
 *
 * Copyright (c) 2008 AUTHORS.txt (http://ui.jquery.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	ui.core.js
 */

(function($) {

$.widget("ui.slider", $.extend({}, $.ui.mouse, {

	_init: function() {

		var self = this;

		this._keySliding = false;

		this._mouseInit();

		this.element
			.addClass("ui-slider"
				+ " ui-slider-" + this._orientation()
				+ " ui-widget"
				+ " ui-widget-content"
				+ " ui-corner-all");

		this.range = $([]);

		if (this.options.range) {
			if (this.options.range === true) {
				//this.range = $('');
				this.range = $('

');
				if (!this.options.values) this.options.values = [this._valueMin(), this._valueMin()];
				if (this.options.values.length && this.options.values.length != 2) {
					this.options.values = [this.options.values[0], this.options.values[0]];
				}
			} else {
				this.range = $('

');
			}
			this.range
				.appendTo(this.element)
				.addClass("ui-slider-range"
					+ " ui-widget-header");

			var oRange = this.options.range, oOrientation = this._orientation();
			(oRange == "min") && (oOrientation == "horizontal") && this.range.css({ left : 0 });
			(oRange == "max") && (oOrientation == "horizontal") && this.range.css({ right : 0 });
			(oRange == "min") && (oOrientation == "vertical") && this.range.css({ bottom : 0 });
			(oRange == "max") && (oOrientation == "vertical") && this.range.css({ top : 0 });
		}

		if ($(".ui-slider-handle", this.element).length == 0)
			$('')
				.appendTo(this.element)
				.addClass("ui-slider-handle");

		if (this.options.values && this.options.values.length) {
			while ($(".ui-slider-handle", this.element).length < this.options.values.length)
				$('')
					.appendTo(this.element)
					.addClass("ui-slider-handle");
		}

		this.handles = $(".ui-slider-handle", this.element)
			.addClass("ui-state-default"
				+ " ui-corner-all");

		this.handle = this.handles.eq(0);

		this.handles.add(this.range).filter("a")
			.click(function(event) { event.preventDefault(); })
			.hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
			.focus(function() { self.handles.removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
			.blur(function() { $(this).removeClass('ui-state-focus'); });

		this.handles.each(function(i) {
			$(this).data("index.ui-slider-handle", i);
		})

		this.handles.keydown(function(event) {
			var index = $(this).data("index.ui-slider-handle");

			if (self.options.disabled)
				return;

			switch (event.keyCode) {
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.END:
				case $.ui.keyCode.UP:
				case $.ui.keyCode.RIGHT:
				case $.ui.keyCode.DOWN:
				case $.ui.keyCode.LEFT:
					if (!self._keySliding) {
						self._keySliding = true;
						$(this).addClass("ui-state-active");
						self._start(event);
					}
					break;
			}

			var curVal, newVal, step = self._step();
			if (self.options.values && self.options.values.length) {
				curVal = newVal = self.values(index);
			} else {
				curVal = newVal = self.value();
			}

			switch (event.keyCode) {
				case $.ui.keyCode.HOME:
					newVal = self._valueMin();
					break;
				case $.ui.keyCode.END:
					newVal = self._valueMax();
					break;
				case $.ui.keyCode.UP:
				case $.ui.keyCode.RIGHT:
					newVal = curVal + step;
					break;
				case $.ui.keyCode.DOWN:
				case $.ui.keyCode.LEFT:
					newVal = curVal - step;
					break;
			}

			self._slide(event, newVal);
		}).keyup(function(event) {
			if (self._keySliding) {
				self._stop(event);
				self._change(event);
				self._keySliding = false;
				$(this).removeClass("ui-state-active");
			}
		});

		this._refreshValue();

	},

	destroy: function() {

		this.handles.remove();

		this.element
			.removeClass("ui-slider"
				+ " ui-slider-horizontal"
				+ " ui-slider-vertical"
				+ " ui-slider-disabled"
				+ " ui-widget"
				+ " ui-widget-content"
				+ " ui-corner-all")
			.removeData("slider")
			.unbind(".slider");

		this._mouseDestroy();

	},

	_mouseCapture: function(event) {

		var o = this.options;

		if (o.disabled)
			return false;

		this._start(event);

		this.elementSize = {
			width: this.element.outerWidth(),
			height: this.element.outerHeight()
		};
		this.elementOffset = this.element.offset();

		var position = { x: event.pageX, y: event.pageY };
		var normValue = this._normValueFromMouse(position);

		var distance = this._valueMax(), closestHandle;
		var self = this;
		this.handles.each(function(i) {
			var thisDistance = Math.abs(normValue - self.values(i));
			if (distance > thisDistance) {
				distance = thisDistance;
				closestHandle = $(this);
			}
		});

		closestHandle
			.addClass("ui-state-active")
			.focus();

		this._slide(event, normValue);

		return true;

	},

	_mouseStart: function(event) {
		return true;
	},

	_mouseDrag: function(event) {
		var position = { x: event.pageX, y: event.pageY };
		var normValue = this._normValueFromMouse(position);

		this._slide(event, normValue);

		return false;
	},

	_mouseStop: function(event) {
		this.handles.removeClass("ui-state-active");
		this._stop(event);
		this._change(event);

		return false;
	},

	_normValueFromMouse: function(position) {

		var pixelTotal, pixelMouse;
		if ('horizontal' == this._orientation()) {
			pixelTotal = this.elementSize.width;
			pixelMouse = position.x - this.elementOffset.left;
		} else {
			pixelTotal = this.elementSize.height;
			pixelMouse = position.y - this.elementOffset.top;
		}

		var percentMouse = (pixelMouse / pixelTotal);
		if (percentMouse > 1) percentMouse = 1;
		if (percentMouse < 0) percentMouse = 0;
		if ('vertical' == this._orientation())
			percentMouse = 1 - percentMouse;

		var valueTotal = this._valueMax() - this._valueMin();

		var valueMouse = percentMouse * valueTotal;

		var valueMouseModStep = valueMouse % this.options.step;

		var normValue = this._valueMin() + valueMouse - valueMouseModStep;

		if (valueMouseModStep > (this.options.step / 2))
			normValue += this.options.step;

		return normValue;
	},

	_start: function(event) {
		this._trigger("start", event, {
			value: this.value()
		});
	},

	_slide: function(event, newVal) {
		if (this.options.values && this.options.values.length) {
			var handle = this.handles.filter(".ui-state-active");
			var index = handle.data("index.ui-slider-handle");
			if (newVal != this.values(index)) {
				// A slide can be canceled by returning false from the slide callback
				var allowed = this._trigger("slide", event, {
					handle: handle,
					value: newVal
				});
				if (allowed !== false)
					this.values(index, newVal);
			}
		} else {
			if (newVal != this.value()) {
				// A slide can be canceled by returning false from the slide callback
				var allowed = this._trigger("slide", event, {
					value: newVal
				});
				if (allowed !== false)
					this._setData('value', newVal);
			}
		}
	},

	_stop: function(event) {
		this._trigger("stop", event, {
			value: this.value()
		});
	},

	_change: function(event) {
		this._trigger("change", event, {
			value: this.value()
		});
	},

	value: function(newValue) {
		if (arguments.length) {
			this._setData("value", newValue);
			this._change();
		}

		return this._value();
	},

	values: function(index, newValue) {
		if (arguments.length > 1) {
			this.options.values[index] = newValue;
			this._refreshValue();
			this._change();
		}

		if (arguments.length) {
			if (this.options.values && this.options.values.length) {
				return this._values(index);
			} else {
				return this.value();
			}
		} else {
			return this._values();
		}
	},

	_setData: function(key, value) {
		$.widget.prototype._setData.apply(this, arguments);

		switch (key) {
			case 'orientation':
				this.element
					.removeClass("ui-slider-horizontal ui-slider-vertical")
					.addClass("ui-slider-" + this._orientation());
				this._refreshValue();
				break;
			case 'value':
				this._refreshValue();
				break;
		}
	},

	_orientation: function() {
		var orientation = this.options.orientation;
		if (orientation != 'horizontal' && orientation != 'vertical')
			orientation = 'horizontal';

		return orientation;
	},

	_step: function() {
		var step = this.options.step;

		return step;
	},

	_value: function() {
		var val = this.options.value;
		if (val < this._valueMin()) val = this._valueMin();
		if (val > this._valueMax()) val = this._valueMax();

		return val;
	},

	_values: function(index) {
		if (arguments.length) {
			var val = this.options.values[index];
			if (val < this._valueMin()) val = this._valueMin();
			if (val > this._valueMax()) val = this._valueMax();

			return val;
		} else {
			return this.options.values;
		}
	},

	_valueMin: function() {
		var valueMin = this.options.min;

		return valueMin;
	},

	_valueMax: function() {
		var valueMax = this.options.max;

		return valueMax;
	},

	_refreshValue: function() {
		var oRange = this.options.range, oOrientation = this._orientation();

		if (this.options.values && this.options.values.length) {
			var self = this, vp0, vp1;
			this.handles.each(function(i, j) {
				var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
				$(this).css(oOrientation == 'horizontal' ? 'left' : 'bottom', valPercent + '%');
				if (self.options.range === true) {
					if (oOrientation == 'horizontal') {
						(i == 0) && self.range.css('left', valPercent + '%');
						(i == 1) && self.range.css('width', (valPercent - lastValPercent) + '%');
					} else {
						(i == 0) && self.range.css('bottom', (valPercent) + '%');
						(i == 1) && self.range.css('height', (valPercent - lastValPercent) + '%');
					}
				}
				lastValPercent = valPercent;
			});
		} else {
			var valPercent = (this.value() - this._valueMin()) / (this._valueMax() - this._valueMin()) * 100;
			this.handle.css(oOrientation == 'horizontal' ? 'left' : 'bottom', valPercent + '%');

			(oRange == "min") && (oOrientation == "horizontal") && this.range.css({ left: 0, width: valPercent + '%' });
			(oRange == "max") && (oOrientation == "horizontal") && this.range.css({ left: valPercent + '%', width: (100 - valPercent) + '%' });
			(oRange == "min") && (oOrientation == "vertical") && this.range.css({ top: (100 - valPercent) + '%', height: valPercent + '%' });
			(oRange == "max") && (oOrientation == "vertical") && this.range.css({ bottom: valPercent + '%', height: (100 - valPercent) + '%' });
		}
	}

}));

$.extend($.ui.slider, {
	getter: "value values",
	version: "@VERSION",
	defaults: {
		delay: 0,
		distance: 0,
		max: 100,
		min: 0,
		orientation: 'horizontal',
		range: false,
		step: 1,
		value: 0,
		values: null
	}
});

})(jQuery);
<commit_msg>slider: added ui.values in the slide callback for a range<commit_after>/*
 * jQuery UI Slider @VERSION
 *
 * Copyright (c) 2008 AUTHORS.txt (http://ui.jquery.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Slider
 *
 * Depends:
 *	ui.core.js
 */

(function($) {

$.widget("ui.slider", $.extend({}, $.ui.mouse, {

	_init: function() {

		var self = this;

		this._keySliding = false;

		this._mouseInit();

		this.element
			.addClass("ui-slider"
				+ " ui-slider-" + this._orientation()
				+ " ui-widget"
				+ " ui-widget-content"
				+ " ui-corner-all");

		this.range = $([]);

		if (this.options.range) {
			if (this.options.range === true) {
				//this.range = $('');
				this.range = $('

');
				if (!this.options.values) this.options.values = [this._valueMin(), this._valueMin()];
				if (this.options.values.length && this.options.values.length != 2) {
					this.options.values = [this.options.values[0], this.options.values[0]];
				}
			} else {
				this.range = $('

');
			}
			this.range
				.appendTo(this.element)
				.addClass("ui-slider-range"
					+ " ui-widget-header");

			var oRange = this.options.range, oOrientation = this._orientation();
			(oRange == "min") && (oOrientation == "horizontal") && this.range.css({ left : 0 });
			(oRange == "max") && (oOrientation == "horizontal") && this.range.css({ right : 0 });
			(oRange == "min") && (oOrientation == "vertical") && this.range.css({ bottom : 0 });
			(oRange == "max") && (oOrientation == "vertical") && this.range.css({ top : 0 });
		}

		if ($(".ui-slider-handle", this.element).length == 0)
			$('')
				.appendTo(this.element)
				.addClass("ui-slider-handle");

		if (this.options.values && this.options.values.length) {
			while ($(".ui-slider-handle", this.element).length < this.options.values.length)
				$('')
					.appendTo(this.element)
					.addClass("ui-slider-handle");
		}

		this.handles = $(".ui-slider-handle", this.element)
			.addClass("ui-state-default"
				+ " ui-corner-all");

		this.handle = this.handles.eq(0);

		this.handles.add(this.range).filter("a")
			.click(function(event) { event.preventDefault(); })
			.hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
			.focus(function() { self.handles.removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
			.blur(function() { $(this).removeClass('ui-state-focus'); });

		this.handles.each(function(i) {
			$(this).data("index.ui-slider-handle", i);
		})

		this.handles.keydown(function(event) {
			var index = $(this).data("index.ui-slider-handle");

			if (self.options.disabled)
				return;

			switch (event.keyCode) {
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.END:
				case $.ui.keyCode.UP:
				case $.ui.keyCode.RIGHT:
				case $.ui.keyCode.DOWN:
				case $.ui.keyCode.LEFT:
					if (!self._keySliding) {
						self._keySliding = true;
						$(this).addClass("ui-state-active");
						self._start(event);
					}
					break;
			}

			var curVal, newVal, step = self._step();
			if (self.options.values && self.options.values.length) {
				curVal = newVal = self.values(index);
			} else {
				curVal = newVal = self.value();
			}

			switch (event.keyCode) {
				case $.ui.keyCode.HOME:
					newVal = self._valueMin();
					break;
				case $.ui.keyCode.END:
					newVal = self._valueMax();
					break;
				case $.ui.keyCode.UP:
				case $.ui.keyCode.RIGHT:
					newVal = curVal + step;
					break;
				case $.ui.keyCode.DOWN:
				case $.ui.keyCode.LEFT:
					newVal = curVal - step;
					break;
			}

			self._slide(event, newVal);
		}).keyup(function(event) {
			if (self._keySliding) {
				self._stop(event);
				self._change(event);
				self._keySliding = false;
				$(this).removeClass("ui-state-active");
			}
		});

		this._refreshValue();

	},

	destroy: function() {

		this.handles.remove();

		this.element
			.removeClass("ui-slider"
				+ " ui-slider-horizontal"
				+ " ui-slider-vertical"
				+ " ui-slider-disabled"
				+ " ui-widget"
				+ " ui-widget-content"
				+ " ui-corner-all")
			.removeData("slider")
			.unbind(".slider");

		this._mouseDestroy();

	},

	_mouseCapture: function(event) {

		var o = this.options;

		if (o.disabled)
			return false;

		this._start(event);

		this.elementSize = {
			width: this.element.outerWidth(),
			height: this.element.outerHeight()
		};
		this.elementOffset = this.element.offset();

		var position = { x: event.pageX, y: event.pageY };
		var normValue = this._normValueFromMouse(position);

		var distance = this._valueMax(), closestHandle;
		var self = this;
		this.handles.each(function(i) {
			var thisDistance = Math.abs(normValue - self.values(i));
			if (distance > thisDistance) {
				distance = thisDistance;
				closestHandle = $(this);
			}
		});

		closestHandle
			.addClass("ui-state-active")
			.focus();

		this._slide(event, normValue);

		return true;

	},

	_mouseStart: function(event) {
		return true;
	},

	_mouseDrag: function(event) {
		var position = { x: event.pageX, y: event.pageY };
		var normValue = this._normValueFromMouse(position);

		this._slide(event, normValue);

		return false;
	},

	_mouseStop: function(event) {
		this.handles.removeClass("ui-state-active");
		this._stop(event);
		this._change(event);

		return false;
	},

	_normValueFromMouse: function(position) {

		var pixelTotal, pixelMouse;
		if ('horizontal' == this._orientation()) {
			pixelTotal = this.elementSize.width;
			pixelMouse = position.x - this.elementOffset.left;
		} else {
			pixelTotal = this.elementSize.height;
			pixelMouse = position.y - this.elementOffset.top;
		}

		var percentMouse = (pixelMouse / pixelTotal);
		if (percentMouse > 1) percentMouse = 1;
		if (percentMouse < 0) percentMouse = 0;
		if ('vertical' == this._orientation())
			percentMouse = 1 - percentMouse;

		var valueTotal = this._valueMax() - this._valueMin();

		var valueMouse = percentMouse * valueTotal;

		var valueMouseModStep = valueMouse % this.options.step;

		var normValue = this._valueMin() + valueMouse - valueMouseModStep;

		if (valueMouseModStep > (this.options.step / 2))
			normValue += this.options.step;

		return normValue;
	},

	_start: function(event) {
		this._trigger("start", event, {
			value: this.value()
		});
	},

	_slide: function(event, newVal) {
		if (this.options.values && this.options.values.length) {
			var handle = this.handles.filter(".ui-state-active");
			var index = handle.data("index.ui-slider-handle");
			if (newVal != this.values(index)) {
				var newValues = this.values();
				newValues[index] = newVal;
				// A slide can be canceled by returning false from the slide callback
				var allowed = this._trigger("slide", event, {
					handle: handle,
					value: newVal,
					values: newValues
				});
				if (allowed !== false)
					this.values(index, newVal);
			}
		} else {
			if (newVal != this.value()) {
				// A slide can be canceled by returning false from the slide callback
				var allowed = this._trigger("slide", event, {
					value: newVal
				});
				if (allowed !== false)
					this._setData('value', newVal);
			}
		}
	},

	_stop: function(event) {
		this._trigger("stop", event, {
			value: this.value()
		});
	},

	_change: function(event) {
		this._trigger("change", event, {
			value: this.value()
		});
	},

	value: function(newValue) {
		if (arguments.length) {
			this._setData("value", newValue);
			this._change();
		}

		return this._value();
	},

	values: function(index, newValue) {
		if (arguments.length > 1) {
			this.options.values[index] = newValue;
			this._refreshValue();
			this._change();
		}

		if (arguments.length) {
			if (this.options.values && this.options.values.length) {
				return this._values(index);
			} else {
				return this.value();
			}
		} else {
			return this._values();
		}
	},

	_setData: function(key, value) {
		$.widget.prototype._setData.apply(this, arguments);

		switch (key) {
			case 'orientation':
				this.element
					.removeClass("ui-slider-horizontal ui-slider-vertical")
					.addClass("ui-slider-" + this._orientation());
				this._refreshValue();
				break;
			case 'value':
				this._refreshValue();
				break;
		}
	},

	_orientation: function() {
		var orientation = this.options.orientation;
		if (orientation != 'horizontal' && orientation != 'vertical')
			orientation = 'horizontal';

		return orientation;
	},

	_step: function() {
		var step = this.options.step;

		return step;
	},

	_value: function() {
		var val = this.options.value;
		if (val < this._valueMin()) val = this._valueMin();
		if (val > this._valueMax()) val = this._valueMax();

		return val;
	},

	_values: function(index) {
		if (arguments.length) {
			var val = this.options.values[index];
			if (val < this._valueMin()) val = this._valueMin();
			if (val > this._valueMax()) val = this._valueMax();

			return val;
		} else {
			return this.options.values;
		}
	},

	_valueMin: function() {
		var valueMin = this.options.min;

		return valueMin;
	},

	_valueMax: function() {
		var valueMax = this.options.max;

		return valueMax;
	},

	_refreshValue: function() {
		var oRange = this.options.range, oOrientation = this._orientation();

		if (this.options.values && this.options.values.length) {
			var self = this, vp0, vp1;
			this.handles.each(function(i, j) {
				var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
				$(this).css(oOrientation == 'horizontal' ? 'left' : 'bottom', valPercent + '%');
				if (self.options.range === true) {
					if (oOrientation == 'horizontal') {
						(i == 0) && self.range.css('left', valPercent + '%');
						(i == 1) && self.range.css('width', (valPercent - lastValPercent) + '%');
					} else {
						(i == 0) && self.range.css('bottom', (valPercent) + '%');
						(i == 1) && self.range.css('height', (valPercent - lastValPercent) + '%');
					}
				}
				lastValPercent = valPercent;
			});
		} else {
			var valPercent = (this.value() - this._valueMin()) / (this._valueMax() - this._valueMin()) * 100;
			this.handle.css(oOrientation == 'horizontal' ? 'left' : 'bottom', valPercent + '%');

			(oRange == "min") && (oOrientation == "horizontal") && this.range.css({ left: 0, width: valPercent + '%' });
			(oRange == "max") && (oOrientation == "horizontal") && this.range.css({ left: valPercent + '%', width: (100 - valPercent) + '%' });
			(oRange == "min") && (oOrientation == "vertical") && this.range.css({ top: (100 - valPercent) + '%', height: valPercent + '%' });
			(oRange == "max") && (oOrientation == "vertical") && this.range.css({ bottom: valPercent + '%', height: (100 - valPercent) + '%' });
		}
	}

}));

$.extend($.ui.slider, {
	getter: "value values",
	version: "@VERSION",
	defaults: {
		delay: 0,
		distance: 0,
		max: 100,
		min: 0,
		orientation: 'horizontal',
		range: false,
		step: 1,
		value: 0,
		values: null
	}
});

})(jQuery);
<|endoftext|>


<commit_before>
md.webrequest = ({storage: {state}, detect}) => {

  var permissions = ['webRequest', 'webRequestBlocking']

  var filter = {
    urls: ['<all_urls>'],
    types: ['main_frame', 'sub_frame']
  }

  var options = ['blocking', 'responseHeaders']

  var onHeadersReceived = ({method, url, responseHeaders}) => {
    if (method !== 'GET') {
      return {responseHeaders}
    }

    var header = responseHeaders.find(({name}) => /^content-type/i.test(name)) || {}
    var origin = detect.match(url)

    if (!detect.header(header.value) && !origin) {
      return {responseHeaders}
    }

    if (origin.csp) {
      responseHeaders = responseHeaders
        .filter(({name}) => !/content-security-policy/i.test(name))
    }

    // ff: markdown `content-type` is not allowed
    if (/Firefox/.test(navigator.userAgent) && detect.header(header.value)) {
      header.value = 'text/plain'
    }

    if (origin.encoding && header.name) {
      var [media] = header.value.split(';')
      header.value = `${media}; charset=${origin.encoding}`
    }

    return {responseHeaders}
  }

  var onCompleted = ({ip, tabId}) => {
    if (ip && ip !== '127.0.0.1') {
      setTimeout(() => {
        chrome.tabs.sendMessage(tabId, {message: 'autoreload'})
      }, 500)
    }
  }

  var events = () => {
    var headers = false
    for (var key in state.origins) {
      if (state.origins[key].csp || state.origins[key].encoding) {
        headers = true
        break
      }
    }

    // ff: webRequest is required permission
    if (/Firefox/.test(navigator.userAgent)) {
      headers = true
    }

    var completed = false
    if (state.content.autoreload) {
      completed = true
    }

    return {headers, completed}
  }

  var perm = (headers, completed, done) => {
    // ff: webRequest is required permission
    if (/Firefox/.test(navigator.userAgent)) {
      done()
    }
    // request permissions
    else if ((headers || completed) && !chrome.webRequest) {
      chrome.permissions.request({permissions}, done)
    }
    // remove permissions
    else if (!headers && !completed && chrome.webRequest) {
      chrome.permissions.remove({permissions}, () => {
        chrome.webRequest = null
        done()
      })
    }
    else {
      done()
    }
  }

  return () => {

    var {headers, completed} = events()

    // remove listeners
    if (chrome.webRequest) {
      if (!headers && !/Firefox/.test(navigator.userAgent)) {
        chrome.webRequest.onHeadersReceived.removeListener(onHeadersReceived)
      }
      if (!completed) {
        chrome.webRequest.onCompleted.removeListener(onCompleted)
      }
    }

    perm(headers, completed, () => {
      // add listeners
      if (headers && !chrome.webRequest.onHeadersReceived.hasListener(onHeadersReceived)) {
        chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, filter, options)
      }
      if (completed && !chrome.webRequest.onCompleted.hasListener(onCompleted)) {
        chrome.webRequest.onCompleted.addListener(onCompleted, filter)
      }
    })
  }
}
<commit_msg>Check for IPv6 localhost IP<commit_after>
md.webrequest = ({storage: {state}, detect}) => {

  var permissions = ['webRequest', 'webRequestBlocking']

  var filter = {
    urls: ['<all_urls>'],
    types: ['main_frame', 'sub_frame']
  }

  var options = ['blocking', 'responseHeaders']

  var onHeadersReceived = ({method, url, responseHeaders}) => {
    if (method !== 'GET') {
      return {responseHeaders}
    }

    var header = responseHeaders.find(({name}) => /^content-type/i.test(name)) || {}
    var origin = detect.match(url)

    if (!detect.header(header.value) && !origin) {
      return {responseHeaders}
    }

    if (origin.csp) {
      responseHeaders = responseHeaders
        .filter(({name}) => !/content-security-policy/i.test(name))
    }

    // ff: markdown `content-type` is not allowed
    if (/Firefox/.test(navigator.userAgent) && detect.header(header.value)) {
      header.value = 'text/plain'
    }

    if (origin.encoding && header.name) {
      var [media] = header.value.split(';')
      header.value = `${media}; charset=${origin.encoding}`
    }

    return {responseHeaders}
  }

  var onCompleted = ({ip, tabId}) => {
    if (ip && ip !== '127.0.0.1' && ip !== '::1') {
      setTimeout(() => {
        chrome.tabs.sendMessage(tabId, {message: 'autoreload'})
      }, 500)
    }
  }

  var events = () => {
    var headers = false
    for (var key in state.origins) {
      if (state.origins[key].csp || state.origins[key].encoding) {
        headers = true
        break
      }
    }

    // ff: webRequest is required permission
    if (/Firefox/.test(navigator.userAgent)) {
      headers = true
    }

    var completed = false
    if (state.content.autoreload) {
      completed = true
    }

    return {headers, completed}
  }

  var perm = (headers, completed, done) => {
    // ff: webRequest is required permission
    if (/Firefox/.test(navigator.userAgent)) {
      done()
    }
    // request permissions
    else if ((headers || completed) && !chrome.webRequest) {
      chrome.permissions.request({permissions}, done)
    }
    // remove permissions
    else if (!headers && !completed && chrome.webRequest) {
      chrome.permissions.remove({permissions}, () => {
        chrome.webRequest = null
        done()
      })
    }
    else {
      done()
    }
  }

  return () => {

    var {headers, completed} = events()

    // remove listeners
    if (chrome.webRequest) {
      if (!headers && !/Firefox/.test(navigator.userAgent)) {
        chrome.webRequest.onHeadersReceived.removeListener(onHeadersReceived)
      }
      if (!completed) {
        chrome.webRequest.onCompleted.removeListener(onCompleted)
      }
    }

    perm(headers, completed, () => {
      // add listeners
      if (headers && !chrome.webRequest.onHeadersReceived.hasListener(onHeadersReceived)) {
        chrome.webRequest.onHeadersReceived.addListener(onHeadersReceived, filter, options)
      }
      if (completed && !chrome.webRequest.onCompleted.hasListener(onCompleted)) {
        chrome.webRequest.onCompleted.addListener(onCompleted, filter)
      }
    })
  }
}
<|endoftext|>


<commit_before>const minimatch = require('minimatch');

const versioning = require('../versioning');
const { mergeChildConfig } = require('../config');

module.exports = {
  applyPackageRules,
};

function applyPackageRules(inputConfig) {
  let config = { ...inputConfig };
  const {
    versionScheme,
    packageFile,
    depType,
    depName,
    currentValue,
    fromVersion,
    updateType,
  } = config;
  const packageRules = config.packageRules || [];
  logger.trace(
    { depName, packageRules },
    `Checking against ${packageRules.length} packageRules`
  );
  packageRules.forEach(packageRule => {
    let {
      paths,
      depTypeList,
      packageNames,
      packagePatterns,
      excludePackageNames,
      excludePackagePatterns,
      matchCurrentVersion,
      updateTypes,
    } = packageRule;
    // Setting empty arrays simplifies our logic later
    paths = paths || [];
    depTypeList = depTypeList || [];
    packageNames = packageNames || [];
    packagePatterns = packagePatterns || [];
    excludePackageNames = excludePackageNames || [];
    excludePackagePatterns = excludePackagePatterns || [];
    matchCurrentVersion = matchCurrentVersion || null;
    updateTypes = updateTypes || [];
    let positiveMatch = false;
    let negativeMatch = false;
    // Massage a positive patterns patch if an exclude one is present
    if (
      (excludePackageNames.length || excludePackagePatterns.length) &&
      !(packageNames.length || packagePatterns.length)
    ) {
      packagePatterns = ['.*'];
    }
    if (paths.length) {
      const isMatch = paths.some(
        rulePath =>
          packageFile.includes(rulePath) || minimatch(packageFile, rulePath)
      );
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (depTypeList.length) {
      const isMatch = depTypeList.includes(depType);
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (updateTypes.length) {
      const isMatch = updateTypes.includes(updateType);
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (packageNames.length || packagePatterns.length) {
      let isMatch = packageNames.includes(depName);
      // name match is "or" so we check patterns if we didn't match names
      if (!isMatch) {
        for (const packagePattern of packagePatterns) {
          const packageRegex = new RegExp(
            packagePattern === '^*$' || packagePattern === '*'
              ? '.*'
              : packagePattern
          );
          if (depName.match(packageRegex)) {
            logger.trace(`${depName} matches against ${packageRegex}`);
            isMatch = true;
          }
        }
      }
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (excludePackageNames.length) {
      const isMatch = excludePackageNames.includes(depName);
      negativeMatch = negativeMatch || isMatch;
      positiveMatch = positiveMatch || !isMatch;
    }
    if (excludePackagePatterns.length) {
      let isMatch = false;
      for (const pattern of excludePackagePatterns) {
        const packageRegex = new RegExp(
          pattern === '^*$' || pattern === '*' ? '.*' : pattern
        );
        if (depName.match(packageRegex)) {
          logger.trace(`${depName} matches against ${packageRegex}`);
          isMatch = true;
        }
      }
      negativeMatch = negativeMatch || isMatch;
      positiveMatch = positiveMatch || !isMatch;
    }
    if (matchCurrentVersion) {
      const { matches, isVersion } = versioning(versionScheme);
      const compareVersion = isVersion(currentValue)
        ? currentValue // it's a version so we can match against it
        : fromVersion; // need to match against this fromVersion, if available
      if (compareVersion) {
        const isMatch = matches(compareVersion, matchCurrentVersion);
        positiveMatch = positiveMatch || isMatch;
        negativeMatch = negativeMatch || !isMatch;
      } else {
        negativeMatch = true;
      }
    }
    // This rule is considered matched if there was at least one positive match and no negative matches
    if (positiveMatch && !negativeMatch) {
      // Package rule config overrides any existing config
      config = mergeChildConfig(config, packageRule);
      delete config.packageNames;
      delete config.packagePatterns;
      delete config.excludePackageNames;
      delete config.excludePackagePatterns;
      delete config.depTypeList;
      delete config.matchCurrentVersion;
    }
  });
  delete config.packageFules;
  return config;
}
<commit_msg>fix: typo delete packageRules<commit_after>const minimatch = require('minimatch');

const versioning = require('../versioning');
const { mergeChildConfig } = require('../config');

module.exports = {
  applyPackageRules,
};

function applyPackageRules(inputConfig) {
  let config = { ...inputConfig };
  const {
    versionScheme,
    packageFile,
    depType,
    depName,
    currentValue,
    fromVersion,
    updateType,
  } = config;
  const packageRules = config.packageRules || [];
  logger.trace(
    { depName, packageRules },
    `Checking against ${packageRules.length} packageRules`
  );
  packageRules.forEach(packageRule => {
    let {
      paths,
      depTypeList,
      packageNames,
      packagePatterns,
      excludePackageNames,
      excludePackagePatterns,
      matchCurrentVersion,
      updateTypes,
    } = packageRule;
    // Setting empty arrays simplifies our logic later
    paths = paths || [];
    depTypeList = depTypeList || [];
    packageNames = packageNames || [];
    packagePatterns = packagePatterns || [];
    excludePackageNames = excludePackageNames || [];
    excludePackagePatterns = excludePackagePatterns || [];
    matchCurrentVersion = matchCurrentVersion || null;
    updateTypes = updateTypes || [];
    let positiveMatch = false;
    let negativeMatch = false;
    // Massage a positive patterns patch if an exclude one is present
    if (
      (excludePackageNames.length || excludePackagePatterns.length) &&
      !(packageNames.length || packagePatterns.length)
    ) {
      packagePatterns = ['.*'];
    }
    if (paths.length) {
      const isMatch = paths.some(
        rulePath =>
          packageFile.includes(rulePath) || minimatch(packageFile, rulePath)
      );
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (depTypeList.length) {
      const isMatch = depTypeList.includes(depType);
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (updateTypes.length) {
      const isMatch = updateTypes.includes(updateType);
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (packageNames.length || packagePatterns.length) {
      let isMatch = packageNames.includes(depName);
      // name match is "or" so we check patterns if we didn't match names
      if (!isMatch) {
        for (const packagePattern of packagePatterns) {
          const packageRegex = new RegExp(
            packagePattern === '^*$' || packagePattern === '*'
              ? '.*'
              : packagePattern
          );
          if (depName.match(packageRegex)) {
            logger.trace(`${depName} matches against ${packageRegex}`);
            isMatch = true;
          }
        }
      }
      positiveMatch = positiveMatch || isMatch;
      negativeMatch = negativeMatch || !isMatch;
    }
    if (excludePackageNames.length) {
      const isMatch = excludePackageNames.includes(depName);
      negativeMatch = negativeMatch || isMatch;
      positiveMatch = positiveMatch || !isMatch;
    }
    if (excludePackagePatterns.length) {
      let isMatch = false;
      for (const pattern of excludePackagePatterns) {
        const packageRegex = new RegExp(
          pattern === '^*$' || pattern === '*' ? '.*' : pattern
        );
        if (depName.match(packageRegex)) {
          logger.trace(`${depName} matches against ${packageRegex}`);
          isMatch = true;
        }
      }
      negativeMatch = negativeMatch || isMatch;
      positiveMatch = positiveMatch || !isMatch;
    }
    if (matchCurrentVersion) {
      const { matches, isVersion } = versioning(versionScheme);
      const compareVersion = isVersion(currentValue)
        ? currentValue // it's a version so we can match against it
        : fromVersion; // need to match against this fromVersion, if available
      if (compareVersion) {
        const isMatch = matches(compareVersion, matchCurrentVersion);
        positiveMatch = positiveMatch || isMatch;
        negativeMatch = negativeMatch || !isMatch;
      } else {
        negativeMatch = true;
      }
    }
    // This rule is considered matched if there was at least one positive match and no negative matches
    if (positiveMatch && !negativeMatch) {
      // Package rule config overrides any existing config
      config = mergeChildConfig(config, packageRule);
      delete config.packageNames;
      delete config.packagePatterns;
      delete config.excludePackageNames;
      delete config.excludePackagePatterns;
      delete config.depTypeList;
      delete config.matchCurrentVersion;
    }
  });
  delete config.packageRules;
  return config;
}
<|endoftext|>


<commit_before>'use strict';

var http = require('http');
var https = require('https');
var Q = require('q');
var eachAsync = require('each-async');

var Reuest = {
  http: http,
  https: https
};

//构建一个本地的缓存，缓存一个项目的http请求，缓存在内存中，缓存时间为60s
var cdnCustom = {};

var util = {
  getDatas: function(projectName, urlsConf, key) {
    var deferred = Q.defer();

    //对每一个页面的接口请求，请求到的数据缓存到内存中60s
    if(typeof cdnCustom[projectName] == 'object') {
      var expires = cdnCustom[projectName].expires, cacheTime = 60000;

      if((Date.now() - expires) > cacheTime) {
        delete cdnCustom[projectName];
        getFromServer();
      } else {
        console.log('====get data from cache====');
        deferred.resolve(cdnCustom[projectName].data);
      }
    } else {
      getFromServer();
    }

    function getFromServer() {
      cdnCustom[projectName] = {
        expires: Date.now(),
        data: {}
      };

      var promiseArr = [];
      var uid = 0, self = this, urlsNameArr = [], urlsArr = [];

      // for (var i = 0; i < urlArr.length; i++) {
      //   var url = urlArr[i];
      //   var def = this.requestUrl(url);
      //   promiseArr.push(def);
      // }
      for(var name in urlsConf) {
        urlsNameArr.push(name);
        urlsArr.push(urlsConf[name]);
      }

      eachAsync(urlsArr, function (url, index, done) {
        var urlName = urlsNameArr[index];
        var def = self.requestUrl(url, urlName);
        promiseArr.push(def);

        if(promiseArr.length === urlsArr.length) {
          Q.all(promiseArr).then(function(data) {
            var ret = {};
            data.forEach(function(result) {
              // var key = (key || 'data') + (uid++);
              ret[result.urlName] = JSON.parse(result.data);
            });
            promiseArr = [];

            //缓存到内存
            cdnCustom[projectName].data = ret;

            deferred.resolve(ret);
          }, function() {
            deferred.resolve(null);
          });
        }

        done();
      }, function (error) {
        console.log('finished');
      });
    }

    return deferred.promise;
  },
  requestUrl: function(url, urlName) {
    var protocol = /https\:/.test(url) ? https : http;
    console.log('请求的url地址是:' + url);
    var deferred = Q.defer();

    protocol.get(url, function(res){
      var statusCode = res.statusCode;
      var contentType = res.headers['content-type'];
      var error;
      if (statusCode !== 200) {
        error = new Error(`Request Failed.\n` +
          `Status Code: ${statusCode}`);
      }
      if (error) {
        console.log(error.message);
        deferred.resolve(null);
        return;
      }
      var rawData = '';
      res.on('data', function(chunk) {
        rawData += chunk;
      });

      res.on('end', function() {
        deferred.resolve({
          urlName: urlName,
          data: rawData
        });
      });
    }).on('error', function(e){
      deferred.resolve(null);
      console.log(`Got error: ${e.message}`);
    });

    return deferred.promise;
  }
}

module.exports = util;<commit_msg>update getData.<commit_after>'use strict';

var http = require('http');
var https = require('https');
var Q = require('q');
var eachAsync = require('each-async');

var Reuest = {
  http: http,
  https: https
};

//构建一个本地的缓存，缓存一个项目的http请求，缓存在内存中，缓存时间为60s
var cdnCustom = {};

var util = {
  getDatas: function(projectName, urlsConf, key) {
    var deferred = Q.defer();

    //对每一个页面的接口请求，请求到的数据缓存到内存中60s
    if(typeof cdnCustom[projectName] == 'object') {
      var expires = cdnCustom[projectName].expires, cacheTime = 60000;

      if((Date.now() - expires) > cacheTime) {
        delete cdnCustom[projectName];
        getFromServer.call(this);
      } else {
        console.log('====get data from cache====');
        deferred.resolve(cdnCustom[projectName].data);
      }
    } else {
      getFromServer.call(this);
    }

    function getFromServer() {
      cdnCustom[projectName] = {
        expires: Date.now(),
        data: {}
      };

      var promiseArr = [];
      var uid = 0, self = this, urlsNameArr = [], urlsArr = [];

      // for (var i = 0; i < urlArr.length; i++) {
      //   var url = urlArr[i];
      //   var def = this.requestUrl(url);
      //   promiseArr.push(def);
      // }
      for(var name in urlsConf) {
        urlsNameArr.push(name);
        urlsArr.push(urlsConf[name]);
      }

      eachAsync(urlsArr, function (url, index, done) {
        var urlName = urlsNameArr[index];
        var def = self.requestUrl(url, urlName);
        promiseArr.push(def);

        if(promiseArr.length === urlsArr.length) {
          Q.all(promiseArr).then(function(data) {
            var ret = {};
            data.forEach(function(result) {
              // var key = (key || 'data') + (uid++);
              ret[result.urlName] = JSON.parse(result.data);
            });
            promiseArr = [];

            //缓存到内存
            cdnCustom[projectName].data = ret;

            deferred.resolve(ret);
          }, function() {
            deferred.resolve(null);
          });
        }

        done();
      }, function (error) {
        console.log('finished');
      });
    }

    return deferred.promise;
  },
  requestUrl: function(url, urlName) {
    var protocol = /https\:/.test(url) ? https : http;
    console.log('请求的url地址是:' + url);
    var deferred = Q.defer();

    protocol.get(url, function(res){
      var statusCode = res.statusCode;
      var contentType = res.headers['content-type'];
      var error;
      if (statusCode !== 200) {
        error = new Error(`Request Failed.\n` +
          `Status Code: ${statusCode}`);
      }
      if (error) {
        console.log(error.message);
        deferred.resolve(null);
        return;
      }
      var rawData = '';
      res.on('data', function(chunk) {
        rawData += chunk;
      });

      res.on('end', function() {
        deferred.resolve({
          urlName: urlName,
          data: rawData
        });
      });
    }).on('error', function(e){
      deferred.resolve(null);
      console.log(`Got error: ${e.message}`);
    });

    return deferred.promise;
  }
}

module.exports = util;<|endoftext|>


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

const logger = require('../handlers/logHandler');
const { prefix } = require('../settings/config.json');

module.exports = (Sequelize, database) => {
  // Models
  database.define('settings', {
    botID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    blacklistedGuilds: {
      type: Sequelize.JSON
    },
    blacklistedUsers: {
      type: Sequelize.JSON
    }
  });

  const Guild = database.define('guild', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    prefix: {
      type: Sequelize.JSON,
      allowNull: false,
      defaultValue: prefix ? [].concat(prefix) : [ '!' ]
    },
    language: {
      type: Sequelize.STRING,
      defaultValue: 'en'
    },
    greet: {
      type: Sequelize.STRING
    },
    greetMessage: {
      type: Sequelize.BLOB
    },
    greetTimeout: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 0
    },
    greetPrivate: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    greetPrivateMessage: {
      type: Sequelize.BLOB
    },
    farewell: {
      type: Sequelize.STRING
    },
    farewellMessage: {
      type: Sequelize.BLOB
    },
    farewellTimeout: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 0
    },
    music: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    chat: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    levelUps: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    levelUpMessages: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    musicTextChannels: {
      type: Sequelize.TEXT,
      unique: true
    },
    musicVoiceChannel: {
      type: Sequelize.STRING,
      unique: true
    },
    musicMasterRole: {
      type: Sequelize.STRING,
      unique: true
    },
    autoAssignableRoles: {
      type: Sequelize.JSON,
      unique: true
    },
    selfAssignableRoles: {
      type: Sequelize.JSON,
      unique: true
    },
    streamerRole: {
      type: Sequelize.STRING,
      unique: true
    },
    filterInvites: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filterLinks: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filterMentions: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filterWords: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filteredWords: {
      type: Sequelize.JSON
    },
    whitelistedDomains: {
      type: Sequelize.JSON
    },
    whitelistedInvites: {
      type: Sequelize.JSON
    },
    slowMode: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    mentionSpamThreshold: {
      type: Sequelize.INTEGER,
      defaultValue: 5
    },
    mentionSpamAction: {
      type: Sequelize.STRING
    },
    warnThreshold: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 5
    },
    warnAction: {
      type: Sequelize.STRING
    },
    serverLog: {
      type: Sequelize.STRING,
      unique: true
    },
    moderationLog: {
      type: Sequelize.STRING,
      unique: true
    },
    moderationCaseNo: {
      type: Sequelize.STRING,
      allowNull: false,
      defaultValue: 1
    },
    starboard: {
      type: Sequelize.STRING,
      unique: true
    },
    announcementChannel: {
      type: Sequelize.STRING,
      unique: true
    },
    reportChannel: {
      type: Sequelize.STRING
    },
    suggestionChannel: {
      type: Sequelize.STRING
    },
    disabledCommands: {
      type: Sequelize.JSON
    },
    onlyMembersWithRoles: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    autoDeleteCommandOutput: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const User = database.define('user', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    bio: {
      type: Sequelize.BLOB
    },
    birthDate: {
      type: Sequelize.DATEONLY
    },
    location: {
      type: Sequelize.STRING
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const GuildMember = database.define('guildMember', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    bastionCurrencies: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    experiencePoints: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    level: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    reputations: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    lastClaimed: {
      type: Sequelize.DATE
    },
    claimStreak: {
      type: Sequelize.TINYINT(3),
      defaultValue: 0
    }
  },
  {
    hooks: {
      beforeCreate: async (user) => {
        await User.upsert({
          userID: user.dataValues.userID
        },
        {
          where: {
            userID: user.dataValues.userID
          },
          fields: [ 'userID' ]
        }).catch(e => {
          logger.error(e);
        });
      },
      afterDestroy: async (user) => {
        try {
          let guildMemberModel = await GuildMember.findOne({
            where: {
              userID: user.dataValues.userID
            }
          });

          // If the user is not present in any guild, remove all user data.
          if (!guildMemberModel) {
            await User.destroy({
              where: {
                userID: user.dataValues.userID
              }
            });
          }
        }
        catch (e) {
          logger.error(e);
        }
      }
    }
  });

  const TextChannel = database.define('textChannel', {
    channelID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true,
      unique: 'guildTextChannel'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildTextChannel'
    },
    votingChannel: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreInviteFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreLinkFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreMentionFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreWordFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreSlowMode: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreStarboard: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    disabledCommands: {
      type: Sequelize.JSON
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const Role = database.define('role', {
    roleID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true,
      unique: 'role'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'role'
    },
    ignoreInviteFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreLinkFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreMentionFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreWordFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreSlowMode: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreStarboard: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    disabledCommands: {
      type: Sequelize.JSON
    },
    level: {
      type: Sequelize.STRING
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const ModerationCase = database.define('moderationCase', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    number: {
      type: Sequelize.STRING,
      allowNull: false
    },
    messageID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true
    }
  });

  const Trigger = database.define('trigger', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    trigger: {
      type: Sequelize.TEXT,
      allowNull: false
    },
    responseMessage: {
      type: Sequelize.TEXT
    },
    responseReactions: {
      type: Sequelize.TEXT
    }
  },
  {
    validate: {
      atLeastOne() {
        if ((this.responseMessage === null) && (this.responseReactions === null)) {
          throw new Error('At least one response type (message/reaction) is required.');
        }
      }
    }
  });

  const ScheduledCommand = database.define('scheduledCommand', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    channelID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    messageID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    cronExp: {
      type: Sequelize.STRING,
      allowNull: false
    },
    command: {
      type: Sequelize.STRING,
      allowNull: false
    },
    arguments: {
      type: Sequelize.TEXT
    }
  });

  const Shop = database.define('shop', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    roles: {
      type: Sequelize.JSON
    },
    custom: {
      type: Sequelize.JSON
    }
  });

  const Streamers = database.define('streamers', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    channelID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true
    },
    mixer: {
      type: Sequelize.JSON
    },
    twitch: {
      type: Sequelize.JSON
    },
    youtube: {
      type: Sequelize.JSON
    }
  });

  const Transaction = database.define('transaction', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    type: {
      type: Sequelize.STRING,
      allowNull: false
    },
    amount: {
      type: Sequelize.TEXT,
      allowNull: false
    },
    note: {
      type: Sequelize.TEXT
    }
  });

  const Items = database.define('items', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    custom: {
      type: Sequelize.JSON
    }
  });

  // Associations
  Guild.Items = Guild.hasMany(Items, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.ModerationCases = Guild.hasMany(ModerationCase, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Roles = Guild.hasMany(Role, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.ScheduledCommands = Guild.hasMany(ScheduledCommand, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Shop = Guild.hasOne(Shop, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Streamers = Guild.hasOne(Streamers, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.TextChannels = Guild.hasMany(TextChannel, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Transactions = Guild.hasMany(Transaction, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Triggers = Guild.hasMany(Trigger, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  User.Items = User.hasMany(Items, {
    foreignKey: 'userID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  User.Transactions = User.hasMany(Transaction, {
    foreignKey: 'userID',
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE'
  });
  User.Guild = User.belongsToMany(Guild, {
    through: 'guildMember',
    foreignKey: 'userID',
    otherKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });

  // Save (sync) models to database.
  database.sync();

  // Return models
  return database.models;
};
<commit_msg>db: change trigger model's responseMessage type to JSON<commit_after>/**
 * @file models
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

const logger = require('../handlers/logHandler');
const { prefix } = require('../settings/config.json');

module.exports = (Sequelize, database) => {
  // Models
  database.define('settings', {
    botID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    blacklistedGuilds: {
      type: Sequelize.JSON
    },
    blacklistedUsers: {
      type: Sequelize.JSON
    }
  });

  const Guild = database.define('guild', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    prefix: {
      type: Sequelize.JSON,
      allowNull: false,
      defaultValue: prefix ? [].concat(prefix) : [ '!' ]
    },
    language: {
      type: Sequelize.STRING,
      defaultValue: 'en'
    },
    greet: {
      type: Sequelize.STRING
    },
    greetMessage: {
      type: Sequelize.BLOB
    },
    greetTimeout: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 0
    },
    greetPrivate: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    greetPrivateMessage: {
      type: Sequelize.BLOB
    },
    farewell: {
      type: Sequelize.STRING
    },
    farewellMessage: {
      type: Sequelize.BLOB
    },
    farewellTimeout: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 0
    },
    music: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    chat: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    levelUps: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    levelUpMessages: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    musicTextChannels: {
      type: Sequelize.TEXT,
      unique: true
    },
    musicVoiceChannel: {
      type: Sequelize.STRING,
      unique: true
    },
    musicMasterRole: {
      type: Sequelize.STRING,
      unique: true
    },
    autoAssignableRoles: {
      type: Sequelize.JSON,
      unique: true
    },
    selfAssignableRoles: {
      type: Sequelize.JSON,
      unique: true
    },
    streamerRole: {
      type: Sequelize.STRING,
      unique: true
    },
    filterInvites: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filterLinks: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filterMentions: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filterWords: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    filteredWords: {
      type: Sequelize.JSON
    },
    whitelistedDomains: {
      type: Sequelize.JSON
    },
    whitelistedInvites: {
      type: Sequelize.JSON
    },
    slowMode: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    mentionSpamThreshold: {
      type: Sequelize.INTEGER,
      defaultValue: 5
    },
    mentionSpamAction: {
      type: Sequelize.STRING
    },
    warnThreshold: {
      type: Sequelize.INTEGER,
      allowNull: false,
      defaultValue: 5
    },
    warnAction: {
      type: Sequelize.STRING
    },
    serverLog: {
      type: Sequelize.STRING,
      unique: true
    },
    moderationLog: {
      type: Sequelize.STRING,
      unique: true
    },
    moderationCaseNo: {
      type: Sequelize.STRING,
      allowNull: false,
      defaultValue: 1
    },
    starboard: {
      type: Sequelize.STRING,
      unique: true
    },
    announcementChannel: {
      type: Sequelize.STRING,
      unique: true
    },
    reportChannel: {
      type: Sequelize.STRING
    },
    suggestionChannel: {
      type: Sequelize.STRING
    },
    disabledCommands: {
      type: Sequelize.JSON
    },
    onlyMembersWithRoles: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    autoDeleteCommandOutput: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const User = database.define('user', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    bio: {
      type: Sequelize.BLOB
    },
    birthDate: {
      type: Sequelize.DATEONLY
    },
    location: {
      type: Sequelize.STRING
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const GuildMember = database.define('guildMember', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    bastionCurrencies: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    experiencePoints: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    level: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    reputations: {
      type: Sequelize.TEXT,
      allowNull: false,
      defaultValue: '0'
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    lastClaimed: {
      type: Sequelize.DATE
    },
    claimStreak: {
      type: Sequelize.TINYINT(3),
      defaultValue: 0
    }
  },
  {
    hooks: {
      beforeCreate: async (user) => {
        await User.upsert({
          userID: user.dataValues.userID
        },
        {
          where: {
            userID: user.dataValues.userID
          },
          fields: [ 'userID' ]
        }).catch(e => {
          logger.error(e);
        });
      },
      afterDestroy: async (user) => {
        try {
          let guildMemberModel = await GuildMember.findOne({
            where: {
              userID: user.dataValues.userID
            }
          });

          // If the user is not present in any guild, remove all user data.
          if (!guildMemberModel) {
            await User.destroy({
              where: {
                userID: user.dataValues.userID
              }
            });
          }
        }
        catch (e) {
          logger.error(e);
        }
      }
    }
  });

  const TextChannel = database.define('textChannel', {
    channelID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true,
      unique: 'guildTextChannel'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildTextChannel'
    },
    votingChannel: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreInviteFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreLinkFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreMentionFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreWordFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreSlowMode: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreStarboard: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    disabledCommands: {
      type: Sequelize.JSON
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const Role = database.define('role', {
    roleID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true,
      unique: 'role'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'role'
    },
    ignoreInviteFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreLinkFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreMentionFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreWordFilter: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreSlowMode: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    ignoreStarboard: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    },
    disabledCommands: {
      type: Sequelize.JSON
    },
    level: {
      type: Sequelize.STRING
    },
    blacklisted: {
      type: Sequelize.BOOLEAN,
      allowNull: false,
      defaultValue: false
    }
  });

  const ModerationCase = database.define('moderationCase', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    number: {
      type: Sequelize.STRING,
      allowNull: false
    },
    messageID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true
    }
  });

  const Trigger = database.define('trigger', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    trigger: {
      type: Sequelize.TEXT,
      allowNull: false
    },
    responseMessage: {
      type: Sequelize.JSON
    },
    responseReactions: {
      type: Sequelize.TEXT
    }
  },
  {
    validate: {
      atLeastOne() {
        if ((this.responseMessage === null) && (this.responseReactions === null)) {
          throw new Error('At least one response type (message/reaction) is required.');
        }
      }
    }
  });

  const ScheduledCommand = database.define('scheduledCommand', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    channelID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    messageID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    cronExp: {
      type: Sequelize.STRING,
      allowNull: false
    },
    command: {
      type: Sequelize.STRING,
      allowNull: false
    },
    arguments: {
      type: Sequelize.TEXT
    }
  });

  const Shop = database.define('shop', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    roles: {
      type: Sequelize.JSON
    },
    custom: {
      type: Sequelize.JSON
    }
  });

  const Streamers = database.define('streamers', {
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      primaryKey: true
    },
    channelID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: true
    },
    mixer: {
      type: Sequelize.JSON
    },
    twitch: {
      type: Sequelize.JSON
    },
    youtube: {
      type: Sequelize.JSON
    }
  });

  const Transaction = database.define('transaction', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false
    },
    type: {
      type: Sequelize.STRING,
      allowNull: false
    },
    amount: {
      type: Sequelize.TEXT,
      allowNull: false
    },
    note: {
      type: Sequelize.TEXT
    }
  });

  const Items = database.define('items', {
    userID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    guildID: {
      type: Sequelize.STRING,
      allowNull: false,
      unique: 'guildMember'
    },
    custom: {
      type: Sequelize.JSON
    }
  });

  // Associations
  Guild.Items = Guild.hasMany(Items, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.ModerationCases = Guild.hasMany(ModerationCase, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Roles = Guild.hasMany(Role, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.ScheduledCommands = Guild.hasMany(ScheduledCommand, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Shop = Guild.hasOne(Shop, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Streamers = Guild.hasOne(Streamers, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.TextChannels = Guild.hasMany(TextChannel, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Transactions = Guild.hasMany(Transaction, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  Guild.Triggers = Guild.hasMany(Trigger, {
    foreignKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  User.Items = User.hasMany(Items, {
    foreignKey: 'userID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });
  User.Transactions = User.hasMany(Transaction, {
    foreignKey: 'userID',
    onDelete: 'NO ACTION',
    onUpdate: 'CASCADE'
  });
  User.Guild = User.belongsToMany(Guild, {
    through: 'guildMember',
    foreignKey: 'userID',
    otherKey: 'guildID',
    onDelete: 'CASCADE',
    onUpdate: 'CASCADE'
  });

  // Save (sync) models to database.
  database.sync();

  // Return models
  return database.models;
};
<|endoftext|>


<commit_before>D.import_port_flavour('from-js', {
  dir: 'in',
  pairup: function(port) {
    var self = this

    this.default_value = 1

    if(this.settings.all.length > 2)
      this.default_value = this.settings.thing

    this.pair = port
    port.pair = this
  },
  enter: function(ship, process) {
    var value = ship !== undefined ? ship : this.default_value
    D.port_standard_enter.call(this, value, process)
  }
})
<commit_msg>code simplification<commit_after>D.import_port_flavour('from-js', {
  dir: 'in',
  outside_add: function(port) {
    this.default_value = this.settings.all.length > 2
                       ? this.settings.thing
                       : 1
  },
  enter: function(ship, process) {
    var value = ship !== undefined ? ship : this.default_value
    D.port_standard_enter.call(this, value, process)
  }
})
<|endoftext|>


<commit_before>//Import/require modules needed to crawl the schoolmaster schedules.
var http = require('http');
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
var mongodb = require('mongodb').MongoClient;

//Define schooltypes that need to be ripped.
var scheduletypes = [
  'Klasrooster',
  'Docentrooster',
  'Leerlingrooster',
  'Lokaalrooster'
];
var schoolid;

//Function for getting pages with http requests.
function get(database) {

  var collection = database.collection('index');
  collection.drop();

  //Go past all of the scheduletypes and download their pages.
  for (scheduletype of scheduletypes) {
    (function (scheduletype) {
      var link = 'http://roosters5.gepro-osi.nl/roosters/rooster.php?school=' + schoolid + '&type=' + scheduletype;

      scheduletype = scheduletype.replace(/rooster/g, '').toLowerCase();

      http.get(link, function (res) {
        var _download = '';

        res.on('data', function (data) {
          _download += data;
        });

        res.on('end', function () {
          var list = extract(_download);

          if (scheduletype == 'leerling') {
            for(studentcategory of list) {
              (function (studentcategory) {

                http.get('http://' + res.req.socket._host + res.req.path + '&afdeling=' + studentcategory, function (res) {
                  var _download = '';

                  res.on('data', function (data) {
                    _download += iconv.decode(data, 'binary');
                  });

                  res.on('end', function () {
                    var list_students = cheerio('select', _download).children();

                    for (student in list_students) {
                      if (!isNaN(student)) {
                        var name = cheerio(list_students[student]).text().split(' - ')[1];
                        var id = cheerio(list_students[student]).val();

                        var database_entry = {
                          'id' : id,
                          'username' : id + name.split(' ')[0].toLowerCase(),
                          'full_name' : name,
                          'first_name' : name.split(' ')[0],
                          'last_name' : name.split(' ').splice(1).join(' '),
                          'studentcategory' : studentcategory,
                          'type' : scheduletype
                        }

                        collection.insert(database_entry, showOutput);
                        if (studentcategory == list[list.length - 1] && student == list_students.length - 1) {
                          database.close();
                        }
                      }
                    }
                  });
                });
              })(studentcategory);
            }
          }
          else {
            for (entry of list) {
              var database_entry = {
                'name' : entry,
                'type' : scheduletype
              }
              collection.insert(database_entry, showOutput);
            }
          }

        });
      });
    })(scheduletype);
  }
}

//Function for extracting the lists with useful information from the crawled pages.
//(e.g Student names/ids, Teacher codes, Chamber numbers)
function extract(page) {
	var array = cheerio('select', page).text().split('\n');
	return array.splice(1, array.length - 2);
}

//Function being called to access functionality from this module.
function crawl(sid) {
  schoolid = sid;
  mongodb.connect('mongodb://wallpiece/roosterio', function (error, database) {
    if (error) console.warn(error);
    get(database);
  })
}

function showOutput(error, message) {
  if (process.argv[2] == '-v') {
    if (error) process.stdout.write(error.toString());
    process.stdout.write(message + '\n');
  }
}

crawl(934);
<commit_msg>Removed redundant comments and made the file a module.<commit_after>var http = require('http');
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
var mongodb = require('mongodb').MongoClient;

var scheduletypes = [
  'Klasrooster',
  'Docentrooster',
  'Leerlingrooster',
  'Lokaalrooster'
];
var schoolid;

//Function for getting pages with http requests.
function get(database) {

  var collection = database.collection('index');
  collection.drop();

  for (scheduletype of scheduletypes) {
    (function (scheduletype) {

      var link = 'http://roosters5.gepro-osi.nl/roosters/rooster.php?school=' + schoolid + '&type=' + scheduletype;

      scheduletype = scheduletype.replace(/rooster/g, '').toLowerCase();

      http.get(link, function (res) {
        var _download = '';

        res.on('data', function (data) {
          _download += data;
        });

        res.on('end', function () {
          var list = extract(_download);

          if (scheduletype == 'leerling') {
            for(studentcategory of list) {
              (function (studentcategory) {

                http.get('http://' + res.req.socket._host + res.req.path + '&afdeling=' + studentcategory, function (res) {
                  var _download = '';

                  res.on('data', function (data) {
                    _download += iconv.decode(data, 'binary');
                  });

                  res.on('end', function () {
                    var list_students = cheerio('select', _download).children();

                    for (student in list_students) {
                      if (!isNaN(student)) {
                        var name = cheerio(list_students[student]).text().split(' - ')[1];
                        var id = cheerio(list_students[student]).val();

                        var database_entry = {
                          'id' : id,
                          'username' : id + name.split(' ')[0].toLowerCase(),
                          'full_name' : name,
                          'first_name' : name.split(' ')[0],
                          'last_name' : name.split(' ').splice(1).join(' '),
                          'studentcategory' : studentcategory,
                          'type' : scheduletype
                        }

                        collection.insert(database_entry, showOutput);
                        if (studentcategory == list[list.length - 1] && student == list_students.length - 1) {
                          database.close();
                        }
                      }
                    }
                  });
                });
              })(studentcategory);
            }
          }
          else {
            for (entry of list) {
              var database_entry = {
                'name' : entry,
                'type' : scheduletype
              }
              collection.insert(database_entry, showOutput);
            }
          }

        });
      });
    })(scheduletype);
  }
}

//Function for extracting the lists with useful information from the crawled pages.
//(e.g Student names/ids, Teacher codes, Chamber numbers)
function extract(page) {
	var array = cheerio('select', page).text().split('\n');
	return array.splice(1, array.length - 2);
}

//Function being called to access functionality from this module.
function crawl(sid) {
  schoolid = sid;
  mongodb.connect('mongodb://wallpiece/roosterio', function (error, database) {
    if (error) console.warn(error);
    get(database);
  })
}

//Redundant function for draining native-mongodb-driver output
function showOutput(error, message) {
  if (process.argv[2] == '-v') {
    if (error) process.stdout.write(error.toString());
    process.stdout.write(message + '\n');
  }
}

module.exports = {
  'crawl' : crawl
}
<|endoftext|>


<commit_before>import analyseJournal from '../analysis/analysis';
import { updateAnalysis } from '../model/state';

const updateAfterAnalyse = reducer => (state, action) => {
  const newState = reducer(state, action);
  const newAnalysis = analyseJournal(newState.journal || []);
  return updateAnalysis(newState)(newAnalysis);
};

export default updateAfterAnalyse;
<commit_msg>Don't run analysis if model wasn't changed<commit_after>import analyseJournal from '../analysis/analysis';
import { updateAnalysis } from '../model/state';

const updateAfterAnalyse = reducer => (state, action) => {
  const newState = reducer(state, action);
  if (newState.journal !== state.journal) {
    const newAnalysis = analyseJournal(newState.journal || []);
    return updateAnalysis(newState)(newAnalysis);
  } else {
    return newState;
  }
};

export default updateAfterAnalyse;
<|endoftext|>


<commit_before>var EventEmitter = require('events');
var iconv = require('iconv-lite');
var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');

function Spider(todo_list, opts, callback) {
    this.todo_list = typeof todo_list === 'string' ? [todo_list] : todo_list;
    this.opts = { //选项默认设置
        retries: 2,
        max_connection: 100,

        save_log: true,
        log_path: '',
        log_frequency: 20,
        log_more: false,

        decode: false,
        debug: false,
        jQ: true,
        save_as_txt: false,
        push_to_db: false
    };

    //让opts变成可选参数，更加灵活
    if (callback) {
        //opts和callback位置可以互换
        var o;
        var i;
        if (typeof opts === 'object') {
            o = this.opts;
            for (i in opts) { //使用参数opts覆盖默认设置
                o[i] = opts[i];
            }
            this.opts = o;
            this.callback = callback;
        } else if (typeof callback === 'object') {
            o = this.opts;
            for (i in callback) {
                o[i] = callback[i];
            }
            this.opts = o;
            this.callback = opts;
        }
    } else {
        this.callback = opts;
    }

    this.done = []; //已完成的链接
    this.fail_todo_list = []; //失败的链接
    this.nervus = new EventEmitter();
    this.conn_num = 0; //当前连接数
    this.stop_add_todo_list = false;
    this.log = [];

    this.todo = todo;
    this.pushLog = pushLog;
    this.initCheckout = initCheckout;
    this.progress = {
        Updata: progressUpdata,
        init: progressInit,
        show: progressShow
    };
    this.crawl = crawl;
    this.work = work;
    this.test = function() {
        this.opts.debug = true;
        this.work();
    };
}

//事件监听初始化、各参数、选项检验、启动工作
function work() {
    var init_result = this.initCheckout();
    if (!init_result) {
        return;
    }

    //事件监听
    var that = this;
    that.nervus.on('crawl', function() {
        if (that.todo_list.length > 0) {
            var next_url = that.todo_list[0];
            that.todo_list.shift();
            that.crawl(next_url);
        }
    });
    that.nervus.on('next', function() {
        // if (that.conn_num > 0) {
        // that.conn_num--; //当conn大于0,说明是某次爬取成功触发的next事件，此时已完成一次连接.
        // }
        if (that.conn_num < that.opts.max_connection) {
            if (that.todo_list.length <= 0 && that.opts.retries > 0) {
                that.todo_list = that.fail_todo_list;
                that.fail_todo_list = [];
                that.opts.retries--;
            }
            if (that.todo_list.length <= 0 && that.conn_num <= 0) {
                that.nervus.emit('finish');
                return true;
            }
            that.nervus.emit('crawl');
        }
    });
    that.nervus.on('back', function() {
        that.conn_num--;
        that.nervus.emit('next');
    });
    that.nervus.on('finish', function() {
        console.log('finish');
        console.log(that.log);
    });

    that.nervus.emit('crawl');
}

function crawl(url) {
    this.conn_num++;
    var that = this;
    this.nervus.emit('next');
    request({
        url: url,
        method: 'GET',
        encoding: null
    }, function(err, res, body) {
        if (err) {
            that.showProgress('Failed', url);
            if (that.opts.debug) { //如果是debug模式，直接报错并退出当前爬取操作
                console.log('========================================');
                console.log('网络request出错 [' + url + '] 建议：检查网络和url参数');
                console.error(err);
                console.log('========================================');
            } else { //如果不是debug模式，错误信息推送到Log，并继续
                that.fail_todo_list.push(url);
                that.pushLog({ type: 'request_failed', url: url, warn: '访问失败', detail: err });
                that.nervus.emit('back');
            }
            return;
        }
        if (that.opts.decode) {
            body = iconv.decode(body, that.opts.decode);
        }
        var result = {
            err: err,
            body: body,
            res: res,
            url: url
        };
        try {
            if (that.opts.jQ) {
                var $ = cheerio.load(body, { decodeEntities: false });
                that.callback($, result);
            } else {
                that.callback(result);
            }
        } catch (e) {
            that.showProgress('Failed', url);
            if (that.opts.debug) {
                console.log('========================================');
                console.log('抓取内容出错 建议：检查callback函数，以及返回正文');
                console.log(e);
                console.log('========================================');
                return;
            } else {
                that.fail_todo_list.push(url);
                that.pushLog({ type: 'callback_failed', url: url, warn: 'callback报错', detail: e });
                that.nervus.emit('back');
                return;
            }
        }
        that.showProgress('Successful', url);
        that.done.push(url);
        that.nervus.emit('back');
    });
}

/**
 * 添加待抓取链接
 * @param {string} new_todo_list 待抓取的url
 */
function todo(new_todo_list) {
    if (this.stop_add_todo_list) {
        return;
    }
    var x = this.todo_list.indexOf(new_todo_list);
    var y = this.done.indexOf(new_todo_list);
    var z = this.fail_todo_list.indexOf(new_todo_list);
    //如果这个链接不存在于待抓取列表、抓取成功列表、抓取失败列表，则添加到待抓取列表
    if (x === -1 && y === -1 && z === -1) {
        this.todo_list.push(new_todo_list);
        return true;
    }
    return false;
}

function todoNow(url) {
    if (this.stop_add_todo_list) return;
    var x = this.todo_list.indexOf(new_todo_list);
    var y = this.done.indexOf(new_todo_list);
    var z = this.fail_todo_list.indexOf(new_todo_list);
    //如果这个链接不存在于待抓取列表、抓取成功列表、抓取失败列表，则添加到待抓取列表
    if (x === -1 && y === -1 && z === -1) {
        this.todo_list.push(new_todo_list);
        return true;
    }
    return false;
}

function pushLog(l) {
    this.log.push({
        time: Date(),
        url: l.url,
        type: l.type,
        detail: l.detail,
        warn: l.warn
    });
}

//爬虫初始化参数检验
function initCheckout() {
    var result = true;
    if (typeof this.todo_list !== 'string' && !Array.isArray(this.todo_list)) {
        console.error('初始化参数出错，您没有正确输入链接字符串或链接字符串的数组');
        result = false;
    }
    if (typeof this.callback !== 'function') {
        console.error('初始化参数出错: callback格式不正确');
        result = false;
    }
    return result;
}

function showProgress(type, url) {
    var all = this.todo_list.length + this.done.length + this.fail_todo_list.length + 1;
    var pro = this.done.length + this.fail_todo_list.length;
    var suc = this.done.length;
    var fail = this.fail_todo_list.length;
    var retries = this.opts.retries;
    var conn = this.conn_num;
    console.log('Pro:[' + pro + '/' + all + ']  retries:' + retries + '  Suc/Fail: (' + suc + '/' + fail + ')  Conn:' + conn + '  ' + type + ' | ' + url);
}

/**
 * 资源池生成函数
 * @param {number}   max      资源池最大容量
 * @param {function} releaseFun 资源池释放函数
 */
function Pool(max, releaseFun) {
    this.data = [];
    this.max = max;
    this.push = function(new_data) {
        this.data.push(new_data);
        if (max && releaseFun) {
            if (this.data.length >= this.max) {
                this.release();
            }
        }
    };
    this.get = function() {
        var d = this.data[0];
        this.data.shift();
        return d;
    };
    this.release = function() {
        var d = this.data;
        this.data = [];
        releaseFun(d);
    };
}

module.exports = Spider;
<commit_msg>change to Pool.prototype<commit_after>var EventEmitter = require('events');
var iconv = require('iconv-lite');
var request = require('request');
var cheerio = require('cheerio');
var fs = require('fs');

function Spider(todo_list, opts, callback) {
    this.todo_list = typeof todo_list === 'string' ? [todo_list] : todo_list;
    this.opts = { //选项默认设置
        retries: 2,
        max_connection: 100,

        save_log: true,
        log_path: '',
        log_frequency: 20,
        log_more: false,

        decode: false,
        debug: false,
        jQ: true,
        save_as_txt: false,
        push_to_db: false
    };

    //让opts变成可选参数，更加灵活
    if (callback) {
        //opts和callback位置可以互换
        var o;
        var i;
        if (typeof opts === 'object') {
            o = this.opts;
            for (i in opts) { //使用参数opts覆盖默认设置
                o[i] = opts[i];
            }
            this.opts = o;
            this.callback = callback;
        } else if (typeof callback === 'object') {
            o = this.opts;
            for (i in callback) {
                o[i] = callback[i];
            }
            this.opts = o;
            this.callback = opts;
        }
    } else {
        this.callback = opts;
    }

    this.done = []; //已完成的链接
    this.fail_todo_list = []; //失败的链接
    this.nervus = new EventEmitter();
    this.conn_num = 0; //当前连接数
    this.stop_add_todo_list = false;
    this.log = [];

    this.progress = {
        Updata: progressUpdata,
        init: progressInit,
        show: progressShow
    };
}

//事件监听初始化、各参数、选项检验、启动工作
Spider.prototype.work = function work() {
    var init_result = this.initCheckout();
    if (!init_result) {
        return;
    }
    //事件监听
    var that = this;
    that.nervus.on('crawl', function() {
        if (that.todo_list.length > 0) {
            var next_url = that.todo_list[0];
            that.todo_list.shift();
            that.crawl(next_url);
        }
    });
    that.nervus.on('next', function() {
        // if (that.conn_num > 0) {
        // that.conn_num--; //当conn大于0,说明是某次爬取成功触发的next事件，此时已完成一次连接.
        // }
        if (that.conn_num < that.opts.max_connection) {
            if (that.todo_list.length <= 0 && that.opts.retries > 0) {
                that.todo_list = that.fail_todo_list;
                that.fail_todo_list = [];
                that.opts.retries--;
            }
            if (that.todo_list.length <= 0 && that.conn_num <= 0) {
                that.nervus.emit('finish');
                return true;
            }
            that.nervus.emit('crawl');
        }
    });
    that.nervus.on('back', function() {
        that.conn_num--;
        that.nervus.emit('next');
    });
    that.nervus.on('finish', function() {
        console.log('finish');
        console.log(that.log);
    });

    that.nervus.emit('crawl');
};

Spider.prototype.test = function test() {
    this.opts.debug = true;
    this.work();
};
Spider.prototype.crawl = function crawl(url) {
    this.conn_num++;
    var that = this;
    this.nervus.emit('next');
    request({
        url: url,
        method: 'GET',
        encoding: null
    }, function(err, res, body) {
        if (err) {
            that.showProgress('Failed', url);
            if (that.opts.debug) { //如果是debug模式，直接报错并退出当前爬取操作
                console.log('========================================');
                console.log('网络request出错 [' + url + '] 建议：检查网络和url参数');
                console.error(err);
                console.log('========================================');
            } else { //如果不是debug模式，错误信息推送到Log，并继续
                that.fail_todo_list.push(url);
                that.pushLog({ type: 'request_failed', url: url, warn: '访问失败', detail: err });
                that.nervus.emit('back');
            }
            return;
        }
        if (that.opts.decode) {
            body = iconv.decode(body, that.opts.decode);
        }
        var result = {
            err: err,
            body: body,
            res: res,
            url: url
        };
        try {
            if (that.opts.jQ) {
                var $ = cheerio.load(body, { decodeEntities: false });
                that.callback($, result);
            } else {
                that.callback(result);
            }
        } catch (e) {
            that.showProgress('Failed', url);
            if (that.opts.debug) {
                console.log('========================================');
                console.log('抓取内容出错 建议：检查callback函数，以及返回正文');
                console.log(e);
                console.log('========================================');
                return;
            } else {
                that.fail_todo_list.push(url);
                that.pushLog({ type: 'callback_failed', url: url, warn: 'callback报错', detail: e });
                that.nervus.emit('back');
                return;
            }
        }
        that.showProgress('Successful', url);
        that.done.push(url);
        that.nervus.emit('back');
    });
}

/**
 * 添加待抓取链接
 * @param {string} new_todo_list 待抓取的url
 */
Spider.prototype.todo = function todo(new_todo_list) {
    if (this.stop_add_todo_list) {
        return;
    }
    var x = this.todo_list.indexOf(new_todo_list);
    var y = this.done.indexOf(new_todo_list);
    var z = this.fail_todo_list.indexOf(new_todo_list);
    //如果这个链接不存在于待抓取列表、抓取成功列表、抓取失败列表，则添加到待抓取列表
    if (x === -1 && y === -1 && z === -1) {
        this.todo_list.push(new_todo_list);
        return true;
    }
    return false;
}

Spider.prototype.todoNow = function todoNow(url) {
    if (this.stop_add_todo_list) return;
    var x = this.todo_list.indexOf(new_todo_list);
    var y = this.done.indexOf(new_todo_list);
    var z = this.fail_todo_list.indexOf(new_todo_list);
    //如果这个链接不存在于待抓取列表、抓取成功列表、抓取失败列表，则添加到待抓取列表
    if (x === -1 && y === -1 && z === -1) {
        this.todo_list.push(new_todo_list);
        return true;
    }
    return false;
}

Spider.prototype.pushLog = function pushLog(l) {
    this.log.push({
        time: Date(),
        url: l.url,
        type: l.type,
        detail: l.detail,
        warn: l.warn
    });
}

//爬虫初始化参数检验
Spider.prototype.initCheckout = function initCheckout() {
    var result = true;
    if (typeof this.todo_list !== 'string' && !Array.isArray(this.todo_list)) {
        console.error('初始化参数出错，您没有正确输入链接字符串或链接字符串的数组');
        result = false;
    }
    if (typeof this.callback !== 'function') {
        console.error('初始化参数出错: callback格式不正确');
        result = false;
    }
    return result;
}

Spider.prototype.showProgress = function showProgress(type, url) {
    var all = this.todo_list.length + this.done.length + this.fail_todo_list.length + 1;
    var pro = this.done.length + this.fail_todo_list.length;
    var suc = this.done.length;
    var fail = this.fail_todo_list.length;
    var retries = this.opts.retries;
    var conn = this.conn_num;
    console.log('Pro:[' + pro + '/' + all + ']  retries:' + retries + '  Suc/Fail: (' + suc + '/' + fail + ')  Conn:' + conn + '  ' + type + ' | ' + url);
}

/**
 * 资源池生成函数
 * @param {number}   max      资源池最大容量
 * @param {function} releaseFun 资源池释放函数
 */
function Pool(max, releaseFun) {
    this.data = [];
    this.max = max;
}
Pool.prototype.push = function(new_data) {
    this.data.push(new_data);
    if (max && releaseFun) {
        if (this.data.length >= this.max) {
            this.release();
        }
    }
};
Pool.prototype.get = function() {
    var d = this.data[0];
    this.data.shift();
    return d;
};
Pool.prototype.release = function() {
    var d = this.data;
    this.data = [];
    releaseFun(d);
};

module.exports = Spider;
<|endoftext|>