<commit_before>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

let instance = null;

const log = require('./logger.js')(__filename);

const Promise = require('bluebird');
const request = require('request');
const rp = require('request-promise');
const SysManager = require('./SysManager.js');
const sysManager = new SysManager('info');

const rclient = require('../util/redis_manager.js').getRedisClient()

const bone = require("../lib/Bone.js");
const IntelTool = require('./IntelTool');
const intelTool = new IntelTool();

const A_WEEK = 3600 * 24 * 7;

/* malware, botnet, spam, phishing, malicious activity, blacklist, dnsbl */
const IGNORED_TAGS = ['dnsbl', 'spam'];

module.exports = class {
    constructor(loglevel) {
        if (instance == null) {
            instance = this;
        }
        return instance;
    }

    action(action, ip, callback) {
        if (action === "ignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':true}, (err)=> {
                callback(err,null);
            });
        } else if (action === "unignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':false}, (err)=> {
                callback(err,null);
            });
        } else if (action === "block") {
        } else if (action === "unblock") {
        } else if (action === "support") {
        }

      bone.intel(ip, "", action, {});
    }

    async cacheLookupAsync(dest, origin) {
      let result;
      try {
        result = await rclient.getAsync("cache.intel:" + origin + ":" + dest);
      } catch (err) {
        // null
      }
      return result;
    }

    cachelookup(ip, origin, callback) {
        rclient.get("cache.intel:" + origin + ":" + ip, (err, result) => {
            callback(err, result);
        });
    }

    cacheAdd(ip, origin, value) {
        if (value == null) {
            value = "none";
        }
        rclient.set("cache.intel:" + origin + ":" + ip, value, (err, result) => {
          rclient.expireat("cache.intel:" + origin + ":" + ip, this.currentTime() + A_WEEK);
        });
    }

    currentTime() {
      return Math.round(Date.now() / 1000);
    }

    async lookupDomain(domain, ip, flowObj) {
      if (!domain || domain === "firewalla.com") {
        return;
      }

      if (await this.isIgnored(domain)) {
        log.info("Ignored domain:", domain, "skip...");
        return;
      }

      log.info("FlowObj:", flowObj);

      let intel = flowObj.intel;

      if (!intel.category) {
        log.info("No intel for domain", domain, "look up from cloud...");
        intel = await this._lookupDomain(domain, ip);
      } else {
        log.info("Intel for domain", domain, " exists in flowObj");
        if (intel.cc) {
          try {
            intel.cc = JSON.parse(intel.cc)[0];
          } catch (err) {
            log.warn("Error when parsing info.cc:", intel.cc, err);
          }
        }
      }
      log.info(`Intel for domain ${domain} is`, intel);

      return intel;
    }

    async isIgnored(target) {
      let data = await rclient.hgetallAsync("intel:action:" + target);
      log.info("Ignore check for domain:", target, " is", data);
      return data && data.ignore;
    }

    async _lookupDomain(domain, ip) {
      let cloudIntel;
      try {
        cloudIntel = await intelTool.checkIntelFromCloud([ip], [domain], 'out');
      } catch (err) {
        log.info("Error when check intel from cloud", err);
      }
      log.info("Cloud intel for ", domain, "is: ", cloudIntel);

      return this.processCloudIntel(cloudIntel[0]);
    }

  processCloudIntel(cloudIntel) {
    if (!cloudIntel) {
      return;
    }

    let intel = {};
    // check if the host matches the result from cloud
    // FIXME: ignore IP check because intel result from cloud does
    // NOT have "ip" all the time.
    if (cloudIntel.apps) {
      intel.apps = JSON.stringify(cloudIntel.apps);
      let keys = Object.keys(cloudIntel.apps);
      if (keys && keys[0]) {
        intel.app = keys[0];
      }
    }

    if (cloudIntel.c) {
      intel.category = cloudIntel.c;
    }

    if (cloudIntel.action && cloudIntel.action.block) {
      intel.action = "block"
    }

    if (cloudIntel.s) {
      intel.s = cloudIntel.s;
    }

    if (cloudIntel.t) {
      intel.t = cloudIntel.t;
    }

    if (cloudIntel.cc) {
      try {
        cloudIntel.cc = JSON.parse(cloudIntel.cc);
        intel.cc = cloudIntel.cc[0];
      } catch (err) {
        intel.cc = cloudIntel.cc;
        log.warn("Error when parsing info.cc:", cloudIntel.cc, err);
      }
    }
    return intel;
  }

    async lookup(ip, intel) {
      if (!ip || ip === "8.8.8.8" || sysManager.isLocalIP(ip)) {
        return;
      }

      let data = await rclient.hgetallAsync("intel:action:" + ip);
      if (data && data.ignore) {
        log.info("Intel:Lookup:Ignored", ip);
        return;
      }

      let result = this.cacheLookupAsync(ip, "cymon");
      if (result && result !== "none") {
        let lobj = await this._location(ip);
        let obj = JSON.parse(result);
        if (!obj || obj.count === 0) {
          obj = {}
          obj.lobj = lobj;
          obj = this._packageIntel(ip, obj, intel);
          return obj;
        } else {
          obj.lobj = lobj;
          log.info("Intel:Location", ip, obj.lobj);
          this._packageCymon(ip, obj);
          return obj;
        }
      } else {
        return this._lookup(ip, intel);
      }
    }

    _packageIntel(ip, obj, intel) {
        let weburl = "https://intel.firewalla.com/";
        log.info("IntelManger:PackageIntel:",ip,JSON.stringify(intel,null,2));
        if (intel == null) {
            return null;
        }
        if (intel.t) {
            obj.count = Math.abs(intel.t/10);
        } else {
            obj.count = 4;
        }
        if (intel.s) {
            obj.severityscore = intel.s;
        } else {
            obj.severityscore = 20;
        }
        obj.summary = "";
        obj.weburl = weburl;
        if (intel.cc) {
            try {
                obj.tags = JSON.parse(intel.cc);
            } catch(e) {
            }
        }
        log.info("IntelManger:PackageIntel:Done",ip,JSON.stringify(intel,null,2),JSON.stringify(obj,null,2));
        return obj;
    }

    _packageCymon(ip, obj) {
        let weburl = "https://cymon.io/" + ip;
        log.info("INFO:------ Intel Information", obj.count);

        let results = obj.results.filter(x => !IGNORED_TAGS.includes(x.tag));
        obj.count = results.length;
        let summary = obj.count + " reported this IP.\n";

        let tags = {};
        for (let r of obj.results) {
            if (r.tag) {
                if (tags[r.tag] == null) {
                    tags[r.tag] = {
                        tag: r.tag,
                        count: 1
                    };
                } else {
                    tags[r.tag].count += 1;
                }
            }
        }

        let tagArray = [], tagCount = 0, severity = 0;
        for (let i in tags) {
            let tag = tags[i];
            tagArray.push(tag);
            if (i.includes("malicious")) {
              severity += tag.count * 3;
            } else if (i.includes("malware")) {
              severity += tag.count * 3;
            } else if (i == "blacklist") {
              severity += tag.count * 3;
            } else {
              severity += 1;
            }
            tagCount += tag.count;
        }

        tagArray.sort((a, b) => b.count - a.count);

        obj.severityscore = severity;
        obj.summary = summary;
        obj.weburl = weburl;
        obj.tags = tagArray;

        if (obj.tags && obj.tags.length > 0) {
          const reasonize = (tag) => `${tag.tag} - ${Math.round(tag.count / tagCount * 100)}%`;
          let reason = "Possibility: ";
            let first = true;
            for (let tag of obj.tags) {
                if (first) {
                    reason += reasonize(tag);
                    first = false;
                } else {
                    reason += ", " + reasonize(tag);
                }
            }
            obj.reason = reason;
        }
    }

    /* curl ipinfo.io/98.124.243.43/
{
  "ip": "98.124.243.43",
  "hostname": "No Hostname",
  "city": "Kirkland",
  "region": "Washington",
  "country": "US",
  "loc": "47.6727,-122.1873",
  "org": "AS21740 eNom, Incorporated",
  "postal": "98033"
 */
  async _location(ip) {
    log.info("Looking up location:", ip);

    let cached = await this.cacheLookupAsync(ip, "ipinfo");

    if (cached) {
      return JSON.parse(cached);
    }

    return Promise.join(
      this._ipInfofromBone(ip),
      this._ipInfofromIpinfo(ip),
      (info1, info2) => Object.assign(info1 ? info1 : {}, info2)
    );
  }

  static async _ipInfofromBone(ip) {
      let result = await bone.intelFinger(ip);
      if (result) {
        return result.ipinfo;
      }
      return null;
    }

  async _ipInfofromIpinfo(ip) {
    const options = {
      uri: "https://ipinfo.io/" + ip,
      method: 'GET',
      family: 4
      // Authorization: 'Token dc30fcd03eddbd95b90bacaea5e5a44b1b60d2f5',
    };

    let body, result;
    try {
      body = await rp(options);
    } catch (err) {
      log.error("Error while requesting", options.uri, err);
      return;
    }

    this.cacheAdd(ip, "ipinfo", body);

    try {
      result = JSON.parse(body);
    } catch (err) {
      log.error("Error when parse body:", body, err);
    }
    return result;
  }

  _lookup(ip, intel) {
    let url = "https://cymon.io/api/nexus/v1/ip/" + ip + "/events?limit=100";

    let options = {
      uri: url,
      method: 'GET',
      family: 4
    };

    this._location(ip)
      .then(lobj => {
        let obj = {lobj};
        log.info("Intel:Location", ip, lobj);
        obj = this._packageIntel(ip, obj, intel);
        return obj;
      })
      .then(obj => {
        rp(options)
          .catch(err => {
            log.info(`Error while requesting ${url}`, err);
          })
          .then(body => {
            this.cacheAdd(ip, "cymon", body);
            let cobj = JSON.parse(body);
            if (cobj) {
              if (cobj.count === 0) {
                log.info("INFO:====== No Intel Information!!", ip, obj);
                callback(null, obj);
              } else {
                cobj.lobj = lobj;
                this._packageCymon(ip, cobj);
                callback(err, cobj, cobj.weburl);
              }
            } else {
              callback(null, obj);
            }
          });
      });
  }
}
<commit_msg>_location enhancement<commit_after>/*    Copyright 2016 Firewalla LLC
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
'use strict';

let instance = null;

const log = require('./logger.js')(__filename);

const Promise = require('bluebird');
const request = require('request');
const rp = require('request-promise');
const SysManager = require('./SysManager.js');
const sysManager = new SysManager('info');

const rclient = require('../util/redis_manager.js').getRedisClient()

const bone = require("../lib/Bone.js");
const IntelTool = require('./IntelTool');
const intelTool = new IntelTool();

const A_WEEK = 3600 * 24 * 7;

/* malware, botnet, spam, phishing, malicious activity, blacklist, dnsbl */
const IGNORED_TAGS = ['dnsbl', 'spam'];

module.exports = class {
    constructor(loglevel) {
        if (instance == null) {
            instance = this;
        }
        return instance;
    }

    action(action, ip, callback) {
        if (action === "ignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':true}, (err)=> {
                callback(err,null);
            });
        } else if (action === "unignore") {
            rclient.hmset("intel:action:"+ip, {'ignore':false}, (err)=> {
                callback(err,null);
            });
        } else if (action === "block") {
        } else if (action === "unblock") {
        } else if (action === "support") {
        }

      bone.intel(ip, "", action, {});
    }

    async cacheLookupAsync(dest, origin) {
      let result;
      try {
        result = await rclient.getAsync("cache.intel:" + origin + ":" + dest);
      } catch (err) {
        // null
      }
      return result;
    }

    cachelookup(ip, origin, callback) {
        rclient.get("cache.intel:" + origin + ":" + ip, (err, result) => {
            callback(err, result);
        });
    }

    cacheAdd(ip, origin, value) {
        if (value == null) {
            value = "none";
        }
        rclient.set("cache.intel:" + origin + ":" + ip, value, (err, result) => {
          rclient.expireat("cache.intel:" + origin + ":" + ip, this.currentTime() + A_WEEK);
        });
    }

    currentTime() {
      return Math.round(Date.now() / 1000);
    }

    async lookupDomain(domain, ip, flowObj) {
      if (!domain || domain === "firewalla.com") {
        return;
      }

      if (await this.isIgnored(domain)) {
        log.info("Ignored domain:", domain, "skip...");
        return;
      }

      log.info("FlowObj:", flowObj);

      let intel = flowObj.intel;

      if (!intel.category) {
        log.info("No intel for domain", domain, "look up from cloud...");
        intel = await this._lookupDomain(domain, ip);
      } else {
        log.info("Intel for domain", domain, " exists in flowObj");
        if (intel.cc) {
          try {
            intel.cc = JSON.parse(intel.cc)[0];
          } catch (err) {
            log.warn("Error when parsing info.cc:", intel.cc, err);
          }
        }
      }
      log.info(`Intel for domain ${domain} is`, intel);

      return intel;
    }

    async isIgnored(target) {
      let data = await rclient.hgetallAsync("intel:action:" + target);
      log.info("Ignore check for domain:", target, " is", data);
      return data && data.ignore;
    }

    async _lookupDomain(domain, ip) {
      let cloudIntel;
      try {
        cloudIntel = await intelTool.checkIntelFromCloud([ip], [domain], 'out');
      } catch (err) {
        log.info("Error when check intel from cloud", err);
      }
      log.info("Cloud intel for ", domain, "is: ", cloudIntel);

      return this.processCloudIntel(cloudIntel[0]);
    }

  processCloudIntel(cloudIntel) {
    if (!cloudIntel) {
      return;
    }

    let intel = {};
    // check if the host matches the result from cloud
    // FIXME: ignore IP check because intel result from cloud does
    // NOT have "ip" all the time.
    if (cloudIntel.apps) {
      intel.apps = JSON.stringify(cloudIntel.apps);
      let keys = Object.keys(cloudIntel.apps);
      if (keys && keys[0]) {
        intel.app = keys[0];
      }
    }

    if (cloudIntel.c) {
      intel.category = cloudIntel.c;
    }

    if (cloudIntel.action && cloudIntel.action.block) {
      intel.action = "block"
    }

    if (cloudIntel.s) {
      intel.s = cloudIntel.s;
    }

    if (cloudIntel.t) {
      intel.t = cloudIntel.t;
    }

    if (cloudIntel.cc) {
      try {
        cloudIntel.cc = JSON.parse(cloudIntel.cc);
        intel.cc = cloudIntel.cc[0];
      } catch (err) {
        intel.cc = cloudIntel.cc;
        log.warn("Error when parsing info.cc:", cloudIntel.cc, err);
      }
    }
    return intel;
  }

    async lookup(ip, intel) {
      if (!ip || ip === "8.8.8.8" || sysManager.isLocalIP(ip)) {
        return;
      }

      let data = await rclient.hgetallAsync("intel:action:" + ip);
      if (data && data.ignore) {
        log.info("Intel:Lookup:Ignored", ip);
        return;
      }

      let result = this.cacheLookupAsync(ip, "cymon");
      if (result && result !== "none") {
        let lobj = await this._location(ip);
        let obj = JSON.parse(result);
        if (!obj || obj.count === 0) {
          obj = {}
          obj.lobj = lobj;
          obj = this._packageIntel(ip, obj, intel);
          return obj;
        } else {
          obj.lobj = lobj;
          log.info("Intel:Location", ip, obj.lobj);
          this._packageCymon(ip, obj);
          return obj;
        }
      } else {
        return this._lookup(ip, intel);
      }
    }

    _packageIntel(ip, obj, intel) {
        let weburl = "https://intel.firewalla.com/";
        log.info("IntelManger:PackageIntel:",ip,JSON.stringify(intel,null,2));
        if (intel == null) {
            return null;
        }
        if (intel.t) {
            obj.count = Math.abs(intel.t/10);
        } else {
            obj.count = 4;
        }
        if (intel.s) {
            obj.severityscore = intel.s;
        } else {
            obj.severityscore = 20;
        }
        obj.summary = "";
        obj.weburl = weburl;
        if (intel.cc) {
            try {
                obj.tags = JSON.parse(intel.cc);
            } catch(e) {
            }
        }
        log.info("IntelManger:PackageIntel:Done",ip,JSON.stringify(intel,null,2),JSON.stringify(obj,null,2));
        return obj;
    }

    _packageCymon(ip, obj) {
        let weburl = "https://cymon.io/" + ip;
        log.info("INFO:------ Intel Information", obj.count);

        let results = obj.results.filter(x => !IGNORED_TAGS.includes(x.tag));
        obj.count = results.length;
        let summary = obj.count + " reported this IP.\n";

        let tags = {};
        for (let r of obj.results) {
            if (r.tag) {
                if (tags[r.tag] == null) {
                    tags[r.tag] = {
                        tag: r.tag,
                        count: 1
                    };
                } else {
                    tags[r.tag].count += 1;
                }
            }
        }

        let tagArray = [], tagCount = 0, severity = 0;
        for (let i in tags) {
            let tag = tags[i];
            tagArray.push(tag);
            if (i.includes("malicious")) {
              severity += tag.count * 3;
            } else if (i.includes("malware")) {
              severity += tag.count * 3;
            } else if (i == "blacklist") {
              severity += tag.count * 3;
            } else {
              severity += 1;
            }
            tagCount += tag.count;
        }

        tagArray.sort((a, b) => b.count - a.count);

        obj.severityscore = severity;
        obj.summary = summary;
        obj.weburl = weburl;
        obj.tags = tagArray;

        if (obj.tags && obj.tags.length > 0) {
          const reasonize = (tag) => `${tag.tag} - ${Math.round(tag.count / tagCount * 100)}%`;
          let reason = "Possibility: ";
            let first = true;
            for (let tag of obj.tags) {
                if (first) {
                    reason += reasonize(tag);
                    first = false;
                } else {
                    reason += ", " + reasonize(tag);
                }
            }
            obj.reason = reason;
        }
    }

    /* curl ipinfo.io/98.124.243.43/
{
  "ip": "98.124.243.43",
  "hostname": "No Hostname",
  "city": "Kirkland",
  "region": "Washington",
  "country": "US",
  "loc": "47.6727,-122.1873",
  "org": "AS21740 eNom, Incorporated",
  "postal": "98033"
 */
  async _location(ip) {
    log.info("Looking up location:", ip);

    let cached = await this.cacheLookupAsync(ip, "ipinfo");

    if (cached) {
      return JSON.parse(cached);
    }

    let ipinfo = await Promise.join(
      this._ipInfoFromBone(ip),
      this._ipInfoFromIpinfo(ip),
      (info1, info2) => Object.assign(info1 ? info1 : {}, info2)
    );

    log.info("Merged ipinfo is:", ipinfo);

    this.cacheAdd(ip, "ipinfo", JSON.stringify(ipinfo));

    return ipinfo;
  }

  static async _ipInfoFromBone(ip) {
      let result = await bone.intelFinger(ip);
      if (result) {
        log.info("ipInfo from bone is:", result.ipinfo);
        return result.ipinfo;
      }
      log.info("ipInfo from bone is:", null);
      return null;
    }

  async _ipInfoFromIpinfo(ip) {
    const options = {
      uri: "https://ipinfo.io/" + ip,
      method: 'GET',
      family: 4
      // Authorization: 'Token dc30fcd03eddbd95b90bacaea5e5a44b1b60d2f5',
    };

    let body, result;
    try {
      body = await rp(options);
    } catch (err) {
      log.error("Error while requesting", options.uri, err);
      return;
    }

    try {
      result = JSON.parse(body);
    } catch (err) {
      log.error("Error when parse body:", body, err);
    }

    log.info("ipInfo from ipinfo is:", result);
    return result;
  }

  _lookup(ip, intel) {
    let url = "https://cymon.io/api/nexus/v1/ip/" + ip + "/events?limit=100";

    let options = {
      uri: url,
      method: 'GET',
      family: 4
    };

    this._location(ip)
      .then(lobj => {
        let obj = {lobj};
        log.info("Intel:Location", ip, lobj);
        obj = this._packageIntel(ip, obj, intel);
        return obj;
      })
      .then(obj => {
        rp(options)
          .catch(err => {
            log.info(`Error while requesting ${url}`, err);
          })
          .then(body => {
            this.cacheAdd(ip, "cymon", body);
            let cobj = JSON.parse(body);
            if (cobj) {
              if (cobj.count === 0) {
                log.info("INFO:====== No Intel Information!!", ip, obj);
                callback(null, obj);
              } else {
                cobj.lobj = lobj;
                this._packageCymon(ip, cobj);
                callback(err, cobj, cobj.weburl);
              }
            } else {
              callback(null, obj);
            }
          });
      });
  }
}
<|endoftext|>


<commit_before>var _ = require('lib/underscore')._;
var ButtonView = require('ui/common/components/ButtonView');

//BasicQuestionView Component Constructor
function PhotoQuestionView(question, image) {

	var self = Ti.UI.createView({
		layout : 'vertical',
		height : Titanium.UI.SIZE
	});

	var pictureButton = new ButtonView('Take a Picture', { 'width' : '48%' });

	var addImageView = function(image) {
		var imageView = Ti.UI.createImageView({
			width : 100,
			height : 100,
			image : image
		});
		self.add(imageView);

		var clearPictureButton = new ButtonView('Clear the Picture', { 'width' : '48%' });

		self.add(clearPictureButton);

		clearPictureButton.addEventListener('click', function() {
			self.image = null;
			self.remove(imageView);
			self.remove(clearPictureButton);
		});
	};

	self.add(pictureButton);

	var resizeImage = function(image) {
		var imageView = Ti.UI.createImageView({
			width : 1280,
			height : (image.height / image.width) * 1280,
			image : image
		});
		var res_image = imageView.toImage().media;
		return res_image;
	};

	pictureButton.addEventListener('click', function() {
		Ti.Media.showCamera({
			success : function(event) {
				if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
					_(self.getChildren()).each(function(childView) {
						if (childView != pictureButton)
							self.remove(childView);
					});
					addImageView(event.media);
					self.image = event.media;

				} else {
					alert("got the wrong type back :" + event.mediaType);
				}
			},
			cancel : function(event) {
			},
			error : function(event) {
				Ti.API.info("camera error");
			},
			autohide : true,
			mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]
		});
	});

	if (image) {
		var imageFile = Ti.Filesystem.getFile(image);
		addImageView(imageFile.read());
	}

	self.getValue = function() {
		if (self.image) {
			filename = "image_" + (new Date()).valueOf() + ".jpg";
			var file = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, filename);
			file.write(resizeImage(self.image));
			return file.nativePath;
		}
		return null;
	};

	return self;
}

module.exports = PhotoQuestionView;
<commit_msg>Resize photos using ImageFactory as soon as they are taken<commit_after>var _ = require('lib/underscore')._;
var ButtonView = require('ui/common/components/ButtonView');

//BasicQuestionView Component Constructor
function PhotoQuestionView(question, image) {

	var self = Ti.UI.createView({
		layout : 'vertical',
		height : Titanium.UI.SIZE
	});

	var pictureButton = new ButtonView('Take a Picture', { 'width' : '48%' });
	var path;

	var addImageView = function(image) {
		var imageView = Ti.UI.createImageView({
			width : 100,
			height : 100,
			image : image
		});
		self.add(imageView);

		var clearPictureButton = new ButtonView('Clear the Picture', { 'width' : '48%' });

		self.add(clearPictureButton);

		clearPictureButton.addEventListener('click', function() {
			self.image = null;
			self.remove(imageView);
			self.remove(clearPictureButton);
		});
	};

	self.add(pictureButton);

	pictureButton.addEventListener('click', function() {
		Ti.Media.showCamera({
			success : function(event) {
				if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
					_(self.getChildren()).each(function(childView) {
						if (childView != pictureButton)
							self.remove(childView);
					});
					addImageView(event.media);
					self.image = event.media;
					var filename = "image_" + (new Date()).valueOf() + ".jpg";
					var ImageFactory = require('ti.imagefactory');
					var file = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory, filename);
					var new_width = 1000;
					var new_height = (self.image.height / self.image.width) * new_width;
					file.write(ImageFactory.imageAsResized(self.image, { width: new_width, height : new_height, quality: 0.7 }));
					path = file.nativePath;

				} else {
					alert("got the wrong type back :" + event.mediaType);
				}
			},
			cancel : function(event) {
			},
			error : function(event) {
				Ti.API.info("camera error");
			},
			autohide : true,
			mediaTypes : [Ti.Media.MEDIA_TYPE_PHOTO]
		});
	});

	if (image) {
		var imageFile = Ti.Filesystem.getFile(image);
		addImageView(imageFile.read());
	}

	self.getValue = function() {
		if (path) {
			Ti.API.info("Photo for photo question is " + path);
			return path;
		}
		return null;
	};

	return self;
}

module.exports = PhotoQuestionView;
<|endoftext|>


<commit_before>function chiral(opts) {
  "use strict";
  var transformListener, startListener, endListener;
  if (typeof opts == 'function') {
    transformListener = opts;
  } else {
    transformListener = opts.transform;
    startListener = opts.down;
    endListener = opts.up;
  }

  var points = [];

  var lastCentroidX;
  var lastCentroidY;
  var thisCentroidX;
  var thisCentroidY;
  var lastPerimeter;
  var thisPerimeter;
  var lastAngularSum;
  var thisAngularSum;
  var sumX = 0;
  var sumY = 0;

  function findPointId(id) {
    for (var i = 0; i < points.length; ++i) {
      if (points[i].id === id) {
        return i;
      }
    }
    return null;
  }

  function angleFromMean(point) {
    return Math.atan2(
      point.y - sumY / points.length,
      point.x - sumX / points.length) + PI;
  }

  function angleFromCentroid(point) {
    return Math.atan2(
      point.y - thisCentroidY,
      point.x - thisCentroidX);
  }

  function comparePoints(m, n) {
    return angleFromMean(m) - angleFromMean(n);
  }

  var PI = Math.PI;
  var TAU = 2*PI;
  var THREEPI = 3*PI;
  function signedAngle(a) {
    return (a % TAU + THREEPI) % TAU - PI;
  }

  function polyRecalc() {
    var i;
    points.sort(comparePoints);
    var limit = points.length - 1;

    var x0, y0, x1, y1;
    function loadxy(point0, point1) {
      x0 = point0.x;
      y0 = point0.y;
      x1 = point1.x;
      y1 = point1.y;
    }

    loadxy(points[0], points[1]);
    var signedArea = x0*y1 - x1*y0;
    thisCentroidX = (x0 + x1)*signedArea;
    thisCentroidY = (y0 + y1)*signedArea;
    thisPerimeter = Math.sqrt(Math.abs(x0-x1)+Math.abs(y0-y1));
    function iterate() {
      var a = x0*y1 - x1*y0;
      signedArea += a;
      thisCentroidX += (x0 + x1)*a;
      thisCentroidY += (y0 + y1)*a;
      thisPerimeter += Math.sqrt(Math.abs(x0-x1)+Math.abs(y0-y1));
    }
    for (i = 1; i < limit; ++i) {
      loadxy(points[i], points[i+1]);
      iterate();
    }
    loadxy(points[limit], points[0]);
    iterate();

    signedArea *= 0.5;
    thisCentroidX /= (6.0*signedArea);
    thisCentroidY /= (6.0*signedArea);

    thisAngularSum = angleFromCentroid(points[0]);
    for (i = 1; i < points.length; ++i) {
      thisAngularSum += angleFromCentroid(points[i]);
    }
  }

  function insert(e) {
    var thisPoint = {
      id: e.pointerId,
      x: e.clientX,
      y: e.clientY
    };
    sumX += thisPoint.x;
    sumY += thisPoint.y;
    if (points.length == 0) {
      points[0] = thisPoint;
      if (startListener) return startListener();
    } else if (points.length == 1) {
      points[1] = thisPoint;
      lastCentroidX = sumX / 2;
      lastCentroidY = sumY / 2;
      // for lines "perimeter" is the square length
      lastPerimeter = Math.abs(thisPoint.x - points[0].x) +
        Math.abs(thisPoint.y - points[0].y);
    } else {
      points[points.length] = thisPoint;
      polyRecalc();
      lastPerimeter = thisPerimeter;
      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastAngularSum = thisAngularSum;
    }
  }

  function adjust(e, thisPointIndex) {
    var thisX = e.clientX;
    var thisY = e.clientY;
    var thisPoint;
    var transform;

    if (points.length == 1) {
      thisPoint = points[0];
      transform = {
        translateX: thisX - thisPoint.x,
        translateY: thisY - thisPoint.y,
        scale: 1,
        rotate: 0
      };
      thisPoint.x = thisX;
      thisPoint.y = thisY;
      return transformListener(transform);
    } else if (points.length == 2) {
      thisPoint = points[thisPointIndex];
      var otherPoint = points[thisPointIndex?0:1];

      var lastAngle = Math.atan2(
        thisPoint.y - otherPoint.y, thisPoint.x - otherPoint.x);
      var thisAngle = Math.atan2(
        thisY - otherPoint.y, thisX - otherPoint.x);

      sumX += thisX - thisPoint.x;
      sumY += thisY - thisPoint.y;
      thisCentroidX = sumX / 2;
      thisCentroidY = sumY / 2;
      // for lines "perimeter" is the square length
      thisPerimeter = Math.abs(thisX - otherPoint.x) +
        Math.abs(thisY - otherPoint.y);

      transform = {
        translateX: thisCentroidX - lastCentroidX,
        translateY: thisCentroidY - lastCentroidY,
        scale: Math.sqrt(thisPerimeter / lastPerimeter),
        rotate: signedAngle(thisAngle - lastAngle)
      };

      thisPoint.x = thisX;
      thisPoint.y = thisY;
      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastPerimeter = thisPerimeter;
      return transformListener(transform);
    } else {
      thisPoint = points[thisPointIndex];
      var lastX = thisPoint.x;
      var lastY = thisPoint.y;

      thisPoint.x = thisX;
      thisPoint.y = thisY;
      sumX += thisX - lastX;
      sumY += thisY - lastY;
      polyRecalc();

      transform = {
        translateX: thisCentroidX - lastCentroidX,
        translateY: thisCentroidY - lastCentroidY,
        scale: thisPerimeter / lastPerimeter,
        rotate: signedAngle(thisAngularSum - lastAngularSum)
      };

      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastPerimeter = thisPerimeter;
      lastAngularSum = thisAngularSum;
      return transformListener(transform);
    }
  }

  function remove(index) {
    sumX -= points[index].x;
    sumY -= points[index].y;
    points.splice(index, 1);
    if (points.length > 2) {
      polyRecalc();
      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastPerimeter = thisPerimeter;
      lastAngularSum = thisAngularSum;
    } else if (points.length == 2) {
      lastCentroidX = sumX / 2;
      lastCentroidY = sumY / 2;
      // for lines "perimeter" is the square length
      lastPerimeter = Math.abs(points[0].x - points[1].x) +
        Math.abs(points[0].y - points[1].y);
    } else if (points.length == 0) {
      if (endListener) return endListener();
    }
  }

  function listener(e) {
    var thisPointIndex;
    switch (e.type) {
      case 'pointerdown':
      // TODO: allow pointers to be added on enter, or move via config
        return insert(e);

      case 'pointermove':
        // if this is a drag
        if (e.buttons & 1) {
          thisPointIndex = findPointId(e.pointerId);
          if (thisPointIndex !== null) {
            return adjust(e, thisPointIndex);
          }
        }
        break;
      case 'pointerup':
      case 'pointercancel':
      case 'pointerleave':
        thisPointIndex = findPointId(e.pointerId);
        if (thisPointIndex !== null) {
          return remove(thisPointIndex);
        }
        break;
    }
  }

  listener.attach = function attachChiralListener(target) {
    target.addEventListener('pointerdown', listener);
    //target.addEventListener('pointerenter', listener);
    target.addEventListener('pointermove', listener);
    target.addEventListener('pointerup', listener);
    target.addEventListener('pointercancel', listener);
    target.addEventListener('pointerleave', listener);
  };
  listener.remove = function removeChiralListener(target) {
    target.removeEventListener('pointerdown', listener);
    //target.removeEventListener('pointerenter', listener);
    target.removeEventListener('pointermove', listener);
    target.removeEventListener('pointerup', listener);
    target.removeEventListener('pointercancel', listener);
    target.removeEventListener('pointerleave', listener);
  };
  return listener;
}
<commit_msg>Ensure stable sort for points at identical angles<commit_after>function chiral(opts) {
  "use strict";
  var transformListener, startListener, endListener;
  if (typeof opts == 'function') {
    transformListener = opts;
  } else {
    transformListener = opts.transform;
    startListener = opts.down;
    endListener = opts.up;
  }

  var points = [];

  var lastCentroidX;
  var lastCentroidY;
  var thisCentroidX;
  var thisCentroidY;
  var lastPerimeter;
  var thisPerimeter;
  var lastAngularSum;
  var thisAngularSum;
  var sumX = 0;
  var sumY = 0;

  function findPointId(id) {
    for (var i = 0; i < points.length; ++i) {
      if (points[i].id === id) {
        return i;
      }
    }
    return null;
  }

  function angleFromMean(point) {
    return Math.atan2(
      point.y - sumY / points.length,
      point.x - sumX / points.length) + PI;
  }

  function angleFromCentroid(point) {
    return Math.atan2(
      point.y - thisCentroidY,
      point.x - thisCentroidX);
  }

  function comparePoints(m, n) {
    var diff = angleFromMean(m) - angleFromMean(n);
    return diff || (m.y - n.y) || (m.x - n.x);
  }

  var PI = Math.PI;
  var TAU = 2*PI;
  var THREEPI = 3*PI;
  function signedAngle(a) {
    return (a % TAU + THREEPI) % TAU - PI;
  }

  function polyRecalc() {
    var i;
    points.sort(comparePoints);
    var limit = points.length - 1;

    var x0, y0, x1, y1;
    function loadxy(point0, point1) {
      x0 = point0.x;
      y0 = point0.y;
      x1 = point1.x;
      y1 = point1.y;
    }

    loadxy(points[0], points[1]);
    var signedArea = x0*y1 - x1*y0;
    thisCentroidX = (x0 + x1)*signedArea;
    thisCentroidY = (y0 + y1)*signedArea;
    thisPerimeter = Math.sqrt(Math.abs(x0-x1)+Math.abs(y0-y1));
    function iterate() {
      var a = x0*y1 - x1*y0;
      signedArea += a;
      thisCentroidX += (x0 + x1)*a;
      thisCentroidY += (y0 + y1)*a;
      thisPerimeter += Math.sqrt(Math.abs(x0-x1)+Math.abs(y0-y1));
    }
    for (i = 1; i < limit; ++i) {
      loadxy(points[i], points[i+1]);
      iterate();
    }
    loadxy(points[limit], points[0]);
    iterate();

    signedArea *= 0.5;
    thisCentroidX /= (6.0*signedArea);
    thisCentroidY /= (6.0*signedArea);

    thisAngularSum = angleFromCentroid(points[0]);
    for (i = 1; i < points.length; ++i) {
      thisAngularSum += angleFromCentroid(points[i]);
    }
  }

  function insert(e) {
    var thisPoint = {
      id: e.pointerId,
      x: e.clientX,
      y: e.clientY
    };
    sumX += thisPoint.x;
    sumY += thisPoint.y;
    if (points.length == 0) {
      points[0] = thisPoint;
      if (startListener) return startListener();
    } else if (points.length == 1) {
      points[1] = thisPoint;
      lastCentroidX = sumX / 2;
      lastCentroidY = sumY / 2;
      // for lines "perimeter" is the square length
      lastPerimeter = Math.abs(thisPoint.x - points[0].x) +
        Math.abs(thisPoint.y - points[0].y);
    } else {
      points[points.length] = thisPoint;
      polyRecalc();
      lastPerimeter = thisPerimeter;
      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastAngularSum = thisAngularSum;
    }
  }

  function adjust(e, thisPointIndex) {
    var thisX = e.clientX;
    var thisY = e.clientY;
    var thisPoint;
    var transform;

    if (points.length == 1) {
      thisPoint = points[0];
      transform = {
        translateX: thisX - thisPoint.x,
        translateY: thisY - thisPoint.y,
        scale: 1,
        rotate: 0
      };
      thisPoint.x = thisX;
      thisPoint.y = thisY;
      return transformListener(transform);
    } else if (points.length == 2) {
      thisPoint = points[thisPointIndex];
      var otherPoint = points[thisPointIndex?0:1];

      var lastAngle = Math.atan2(
        thisPoint.y - otherPoint.y, thisPoint.x - otherPoint.x);
      var thisAngle = Math.atan2(
        thisY - otherPoint.y, thisX - otherPoint.x);

      sumX += thisX - thisPoint.x;
      sumY += thisY - thisPoint.y;
      thisCentroidX = sumX / 2;
      thisCentroidY = sumY / 2;
      // for lines "perimeter" is the square length
      thisPerimeter = Math.abs(thisX - otherPoint.x) +
        Math.abs(thisY - otherPoint.y);

      transform = {
        translateX: thisCentroidX - lastCentroidX,
        translateY: thisCentroidY - lastCentroidY,
        scale: Math.sqrt(thisPerimeter / lastPerimeter),
        rotate: signedAngle(thisAngle - lastAngle)
      };

      thisPoint.x = thisX;
      thisPoint.y = thisY;
      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastPerimeter = thisPerimeter;
      return transformListener(transform);
    } else {
      thisPoint = points[thisPointIndex];
      var lastX = thisPoint.x;
      var lastY = thisPoint.y;

      thisPoint.x = thisX;
      thisPoint.y = thisY;
      sumX += thisX - lastX;
      sumY += thisY - lastY;
      polyRecalc();

      transform = {
        translateX: thisCentroidX - lastCentroidX,
        translateY: thisCentroidY - lastCentroidY,
        scale: thisPerimeter / lastPerimeter,
        rotate: signedAngle(thisAngularSum - lastAngularSum) / points.length
      };

      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastPerimeter = thisPerimeter;
      lastAngularSum = thisAngularSum;
      return transformListener(transform);
    }
  }

  function remove(index) {
    sumX -= points[index].x;
    sumY -= points[index].y;
    points.splice(index, 1);
    if (points.length > 2) {
      polyRecalc();
      lastCentroidX = thisCentroidX;
      lastCentroidY = thisCentroidY;
      lastPerimeter = thisPerimeter;
      lastAngularSum = thisAngularSum;
    } else if (points.length == 2) {
      lastCentroidX = sumX / 2;
      lastCentroidY = sumY / 2;
      // for lines "perimeter" is the square length
      lastPerimeter = Math.abs(points[0].x - points[1].x) +
        Math.abs(points[0].y - points[1].y);
    } else if (points.length == 0) {
      if (endListener) return endListener();
    }
  }

  function listener(e) {
    var thisPointIndex;
    switch (e.type) {
      case 'pointerdown':
      // TODO: allow pointers to be added on enter, or move via config
        return insert(e);

      case 'pointermove':
        // if this is a drag
        if (e.buttons & 1) {
          thisPointIndex = findPointId(e.pointerId);
          if (thisPointIndex !== null) {
            return adjust(e, thisPointIndex);
          }
        }
        break;
      case 'pointerup':
      case 'pointercancel':
      case 'pointerleave':
        thisPointIndex = findPointId(e.pointerId);
        if (thisPointIndex !== null) {
          return remove(thisPointIndex);
        }
        break;
    }
  }

  listener.attach = function attachChiralListener(target) {
    target.addEventListener('pointerdown', listener);
    //target.addEventListener('pointerenter', listener);
    target.addEventListener('pointermove', listener);
    target.addEventListener('pointerup', listener);
    target.addEventListener('pointercancel', listener);
    target.addEventListener('pointerleave', listener);
  };
  listener.remove = function removeChiralListener(target) {
    target.removeEventListener('pointerdown', listener);
    //target.removeEventListener('pointerenter', listener);
    target.removeEventListener('pointermove', listener);
    target.removeEventListener('pointerup', listener);
    target.removeEventListener('pointercancel', listener);
    target.removeEventListener('pointerleave', listener);
  };
  return listener;
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var fs        = require('fs');
var net       = require('net');
var events    = require('events');
var path      = require('path');

var irc = {};

var config_path = (process.env.IRC_NODE_PATH ||
                   process.env[(process.platform === 'win32') ?
                   'USERPROFILE' : 'HOME'] + '/.ircnode');
var config_file = config_path + '/config';
var user_file   = config_path + '/users.json';
var plugin_dir  = config_path + '/plugins/';
var log_file    = config_path + '/bot.log';
var lock_file   = '/tmp/ircnode.pid';

irc.auth_levels = [ 'admin', 'owner' ];

var exists = path.existsSync(config_path);
if (!exists) {
  fs.mkdirSync(config_path, '0755');
  fs.mkdir(plugin_dir, '0755');
}

var review_required = false;
[config_file, user_file].forEach(function (file) {
  var exists = path.existsSync(file);
  if (!exists) {
    var sample_file = './' + path.basename(file) + '.sample';
    fs.openSync(file, 'w+');
    fs.writeFileSync(file, fs.readFileSync(sample_file));
    console.log('Creating a new ' + file + ' + file.');
    review_required = true;
  }
});
if (review_required) {
  console.log('Please review the configuration files in ' + config_path);
  process.exit();
}

irc.userLoop = setInterval(function () {
  fs.writeFile(user_file, JSON.stringify(irc.users, null, 2));
}, 20000);

irc.config  = JSON.parse(fs.readFileSync(config_file));
irc.users   = JSON.parse(fs.readFileSync(user_file));

irc.command_char = '!';
irc.debug = process.env.IRC_NODE_DEBUG !== 'false';
irc.emitter = new events.EventEmitter();

var args = process.argv;
var dPID;

switch (args[2]) {
case "start":
  if (path.existsSync(lock_file)) {
    console.log('IRC Node seems to be already running on this system!');
    console.log('If this is not true, please delete the ' + lock_file);
    process.exit(0);
  } else {
    try {
      var daemon = require('daemon');
    } catch (err) {
      if (process.platform === 'win32') {
        console.log('There is no daemon support for Windows.');
      } else {
        console.log('You do not have daemon.node available. Please');
        console.log('run \'npm install daemon\' to install it to the');
        console.log('working directory.');
      }
      console.log('You can still launch the bot without daemon');
      console.log('by simply launching it without any arguments.')
      process.exit(0);
      break;
    }
    dPID = daemon.start(fs.openSync(log_file, 'a+'));
    daemon.lock(lock_file);
  }
  break;

case "restart":
  if (!path.existsSync(lock_file)) {
    console.log('IRC Node was not running before on this system!');
  } else {
    process.kill(parseInt(fs.readFileSync(lock_file), 10));
    fs.unlinkSync(lock_file);
  }
  try {
    var daemon = require('daemon');
  } catch (err) {
    if (process.platform === 'win32') {
      console.log('There is no daemon support for Windows.');
    } else {
      console.log('You do not have daemon.node available. Please');
      console.log('run \'npm install daemon\' to install it to the');
      console.log('working directory.');
    }
    console.log('You can still launch the bot without daemon');
    console.log('by simply launching it without any arguments.');
    process.exit(0);
    break;
  }
  dPID = daemon.start(fs.openSync(log_file, 'a+'));
  daemon.lock(lock_file);
  break;

case "stop":
  if (!path.existsSync(lock_file)) {
    console.log('IRC Node does not seem to be running on this system!');
  } else {
    process.kill(parseInt(fs.readFileSync(lock_file), 10));
    fs.unlinkSync(lock_file);
  }
  process.exit(0);
  break;
}

irc.check_level = function (nick, level, callback) {
  if (typeof irc.users[nick] === 'undefined')
    callback(false);
  else if (typeof irc.users[nick].auth === 'undefined')
    callback(false);
  else if (irc.auth_levels.indexOf(level) !== -1) {
    var listener = function (data) {
      var params = data.split(' ').slice(4);
      var source = data.slice(0, data.indexOf('!'));
      if (params.length < 2) return;
      if (source !== 'NickServ') return;
      if (params[params.length - 2] === nick) {
        irc.emitter.removeListener('NOTICE', listener);
        if (params[params.length - 1] === '3')
          callback(true);
        else
          callback(false);
      }
    };
    irc.emitter.on('NOTICE', listener);
    irc.privmsg('NickServ', 'ACC ' + nick);
    irc.privmsg('NickServ', 'STATUS ' + nick);
  } else
    callback(false);
};

irc.is_admin = function (nick, callback) {
  irc.check_level(nick, 'admin', callback);
};

irc.is_owner = function (nick, callback) {
  irc.check_level(nick, 'owner', callback);
};

irc.privmsg  = function (target, msg) {
  irc._socket.write('PRIVMSG ' + target + ' :' + msg + '\r\n');
};

irc.splitcmd = function (data) {
  var action = {};
  var params = data.split(' ');

  var nickuser = data.substring(0, data.indexOf(' '));
  action.nick = nickuser.split('!')[0];
  action.user = nickuser.split('!')[1].split('@')[0];
  action.host = nickuser.split('!')[1].split('@')[1];

  action.channel = params[2];
  if (action.channel === irc.config.nick)
    action.source = action.nick;
  else
    action.source = action.channel;

  params[3] = params[3].slice(2);

  action.cmd = params[3];
  action.params = params.slice(4);
  action.data   = data;

  return action;
};

irc.act = function (options, callback) {
  if (irc.debug) console.log(options);
  var string = options.action + ' ';
  if (typeof options.params !== 'undefined') {
    string += options.params.join(' ');
  }
  if (typeof options.longParam !== 'undefined') {
    string += ' :' + options.longParam;
  }
  if (irc.debug) console.log(string);
  irc._socket.write(string + '\r\n', callback);
};

irc.join = function (channel, callback) {
  irc.act({action: 'JOIN', params: [channel]}, callback);
};

irc.part = function (channel, msg, callback) {
  irc.act({action: 'PART', params: [channel, msg]}, callback);
};

irc.nick = function (nick, callback) {
  irc.act({action: 'NICK', params: [nick]}, callback);
};

irc.user = function (user, mode, realName, callback) {
  irc.act({action: 'USER', params: [user, mode, '*'],
          longParam: realName}, callback);
};

irc.quit = function (msg, callback) {
  irc.act({action: 'QUIT', params: [msg]}, function () {
    if (path.existsSync(lock_file))
      fs.unlinkSync(lock_file);
    callback();
    process.exit(0);
  });
};

irc._socket = net.connect(irc.config.port, irc.config.address, function () {
  var nick      = irc.config.nick;
  var user      = irc.config.user;
  var realName  = irc.config.realName;
  var chan      = irc.config.chan;

  irc.nick(nick, function () {
    irc.user(user, '8', realName, function () {
      var has_admin = false;
      for (var u in irc.users) {
        if (typeof irc.users[u] !== 'undefined')
          if (typeof irc.users[u].auth !== 'undefined')
            if (irc.users[u].auth === 'admin' || irc.users[u].auth === 'owner')
              has_admin = true;
      }
      if (!has_admin) {
        throw ("An admin must be configured in users.json!");
      }

      if (chan instanceof Array) {
        for (var i = 0, l = chan.length; i < l; i += 1) {
          irc.join(chan[i]);
        }
      } else {
        irc.join(chan);
      }
    });
  });
});

irc._socket.on('data', function (data) {
  data = data.toString();

  if (irc.debug) {
    console.log(data);
  }

  var params = data.split(' ');
  if (data[0] === ':') {
    // Chop off initial colon, send to emitter.
    // also chop off \r\n
    irc.emitter.emit(params[1], data.slice(1, -2));
  } else {
    irc.emitter.emit(params[0], data);
  }
});

irc.emitter.on('PING', function (data) {
  irc._socket.write('PONG ' + data.slice(data.indexOf(':')) + '\r\n');
});

irc.emitter.on('PRIVMSG', function (data) {

  // Look for first character of the message.
  if (data[data.indexOf(':') + 1] === irc.command_char) {
    var action = irc.splitcmd(data);
    if (irc.debug) console.log(action);
    irc.emitter.emit(action.cmd, action);
  }
});

global.irc = irc;
irc.plugins = [];
fs.readdir(plugin_dir, function (err, files) {
  for (var i = 0, len = files.length; i < len; i += 1) {
    var plugin = require(plugin_dir + files[i]);
    plugin.enabled = true;
    irc.plugins.push(plugin);
    irc.emitter.on(plugin.name, plugin.handler);
  }
});

irc.emitter.on('disable', function (act) {
  irc.check_level(act.nick, 'admin', function (is_admin) {
    if (is_admin) {
      for (var p in irc.plugins) {
        if (irc.plugins[p].name === act.params[0]) {
          irc.plugins[p].enabled = false;
          irc.emitter.removeListener(irc.plugins[p].name, irc.plugins[p].handler);
          irc.privmsg(act.source, act.params[0] + ' disabled');
        }
      }
    } else {
      irc.privmsg(act.source, 'ERROR: not authorized');
    }
  });
});

irc.emitter.on('enable', function (act) {
  irc.check_level(act.nick, 'admin', function (is_admin) {
    if (is_admin) {
      for (var p in irc.plugins) {
        if (irc.plugins[p].name === act.params[0] &&
            irc.plugins[p].enabled === false) {
          irc.plugins[p].enabled = true;
          irc.emitter.on(irc.plugins[p].name, irc.plugins[p].handler);
          irc.privmsg(act.source, act.params[0] + ' enabled');
        }
      }
    } else {
      irc.privmsg(act.source, 'ERROR: not authorized');
    }
  });
});

irc.emitter.on('set_auth', function (act) {
  var nick  = act.params[0];
  var level = act.params[1];
  var user  = irc.users[nick];

  if (typeof user === 'undefined')
    irc.users[nick] = {};

  if (act.params.length < 2) {
    irc.privmsg(act.source, 'ERROR: Insufficient parameters');
    return (1);
  }
  if (level !== 'user' && level !== 'owner' && level !== 'admin') {
    irc.privmsg(act.source, 'ERROR: Invalid parameter: ' + level);
    return (1);
  }
  irc.check_level(act.nick, 'owner', function (is_owner) {
    if (is_owner) {
      if (nick === act.nick) {
        irc.privmsg(act.source, 'ERROR: Cannot change your own permissions!');
      } else {
        user.auth = level;
        irc.privmsg(act.source, nick + ' made to ' + level);
      }
    } else {
      irc.privmsg(act.source, 'ERROR: Insufficient privileges');
    }
  });
});

irc.emitter.on('PRIVMSG', function (data) {
  var nick = data.slice(0, data.indexOf('!'));
  if (typeof irc.users[nick] === 'undefined') {
    irc.users[nick] = {};
  }
  if (data.split(' ')[2] !== irc.config.nick) {
    irc.users[nick].seen_time = new Date().toUTCString();
    irc.users[nick].seen_msg  = data.slice(data.indexOf(':') + 1);
    irc.users[nick].seen_channel = data.split(' ')[2];
  }
});

irc.emitter.on('seen', function (act) {
  var nick = act.params[0] ? act.params : act.nick;
  if (typeof irc.users[nick] === 'undefined' ||
      typeof irc.users[nick].seen_msg === 'undefined' ||
      typeof irc.users[nick].seen_time === 'undefined') {
    irc.privmsg(act.source, 'Unknown nick: ' + nick);
    return (1);
  }
  irc.privmsg(act.source, nick + ' last seen: ' + irc.users[nick].seen_time +
              " saying '" + irc.users[nick].seen_msg + "' in " +
              irc.users[nick].seen_channel);
});

<commit_msg>added missing semicolon, now passes jshint<commit_after>#!/usr/bin/env node
var fs        = require('fs');
var net       = require('net');
var events    = require('events');
var path      = require('path');

var irc = {};

var config_path = (process.env.IRC_NODE_PATH ||
                   process.env[(process.platform === 'win32') ?
                   'USERPROFILE' : 'HOME'] + '/.ircnode');
var config_file = config_path + '/config';
var user_file   = config_path + '/users.json';
var plugin_dir  = config_path + '/plugins/';
var log_file    = config_path + '/bot.log';
var lock_file   = '/tmp/ircnode.pid';

irc.auth_levels = [ 'admin', 'owner' ];

var exists = path.existsSync(config_path);
if (!exists) {
  fs.mkdirSync(config_path, '0755');
  fs.mkdir(plugin_dir, '0755');
}

var review_required = false;
[config_file, user_file].forEach(function (file) {
  var exists = path.existsSync(file);
  if (!exists) {
    var sample_file = './' + path.basename(file) + '.sample';
    fs.openSync(file, 'w+');
    fs.writeFileSync(file, fs.readFileSync(sample_file));
    console.log('Creating a new ' + file + ' + file.');
    review_required = true;
  }
});
if (review_required) {
  console.log('Please review the configuration files in ' + config_path);
  process.exit();
}

irc.userLoop = setInterval(function () {
  fs.writeFile(user_file, JSON.stringify(irc.users, null, 2));
}, 20000);

irc.config  = JSON.parse(fs.readFileSync(config_file));
irc.users   = JSON.parse(fs.readFileSync(user_file));

irc.command_char = '!';
irc.debug = process.env.IRC_NODE_DEBUG !== 'false';
irc.emitter = new events.EventEmitter();

var args = process.argv;
var dPID;

switch (args[2]) {
case "start":
  if (path.existsSync(lock_file)) {
    console.log('IRC Node seems to be already running on this system!');
    console.log('If this is not true, please delete the ' + lock_file);
    process.exit(0);
  } else {
    try {
      var daemon = require('daemon');
    } catch (err) {
      if (process.platform === 'win32') {
        console.log('There is no daemon support for Windows.');
      } else {
        console.log('You do not have daemon.node available. Please');
        console.log('run \'npm install daemon\' to install it to the');
        console.log('working directory.');
      }
      console.log('You can still launch the bot without daemon');
      console.log('by simply launching it without any arguments.');
      process.exit(0);
      break;
    }
    dPID = daemon.start(fs.openSync(log_file, 'a+'));
    daemon.lock(lock_file);
  }
  break;

case "restart":
  if (!path.existsSync(lock_file)) {
    console.log('IRC Node was not running before on this system!');
  } else {
    process.kill(parseInt(fs.readFileSync(lock_file), 10));
    fs.unlinkSync(lock_file);
  }
  try {
    var daemon = require('daemon');
  } catch (err) {
    if (process.platform === 'win32') {
      console.log('There is no daemon support for Windows.');
    } else {
      console.log('You do not have daemon.node available. Please');
      console.log('run \'npm install daemon\' to install it to the');
      console.log('working directory.');
    }
    console.log('You can still launch the bot without daemon');
    console.log('by simply launching it without any arguments.');
    process.exit(0);
    break;
  }
  dPID = daemon.start(fs.openSync(log_file, 'a+'));
  daemon.lock(lock_file);
  break;

case "stop":
  if (!path.existsSync(lock_file)) {
    console.log('IRC Node does not seem to be running on this system!');
  } else {
    process.kill(parseInt(fs.readFileSync(lock_file), 10));
    fs.unlinkSync(lock_file);
  }
  process.exit(0);
  break;
}

irc.check_level = function (nick, level, callback) {
  if (typeof irc.users[nick] === 'undefined')
    callback(false);
  else if (typeof irc.users[nick].auth === 'undefined')
    callback(false);
  else if (irc.auth_levels.indexOf(level) !== -1) {
    var listener = function (data) {
      var params = data.split(' ').slice(4);
      var source = data.slice(0, data.indexOf('!'));
      if (params.length < 2) return;
      if (source !== 'NickServ') return;
      if (params[params.length - 2] === nick) {
        irc.emitter.removeListener('NOTICE', listener);
        if (params[params.length - 1] === '3')
          callback(true);
        else
          callback(false);
      }
    };
    irc.emitter.on('NOTICE', listener);
    irc.privmsg('NickServ', 'ACC ' + nick);
    irc.privmsg('NickServ', 'STATUS ' + nick);
  } else
    callback(false);
};

irc.is_admin = function (nick, callback) {
  irc.check_level(nick, 'admin', callback);
};

irc.is_owner = function (nick, callback) {
  irc.check_level(nick, 'owner', callback);
};

irc.privmsg  = function (target, msg) {
  irc._socket.write('PRIVMSG ' + target + ' :' + msg + '\r\n');
};

irc.splitcmd = function (data) {
  var action = {};
  var params = data.split(' ');

  var nickuser = data.substring(0, data.indexOf(' '));
  action.nick = nickuser.split('!')[0];
  action.user = nickuser.split('!')[1].split('@')[0];
  action.host = nickuser.split('!')[1].split('@')[1];

  action.channel = params[2];
  if (action.channel === irc.config.nick)
    action.source = action.nick;
  else
    action.source = action.channel;

  params[3] = params[3].slice(2);

  action.cmd = params[3];
  action.params = params.slice(4);
  action.data   = data;

  return action;
};

irc.act = function (options, callback) {
  if (irc.debug) console.log(options);
  var string = options.action + ' ';
  if (typeof options.params !== 'undefined') {
    string += options.params.join(' ');
  }
  if (typeof options.longParam !== 'undefined') {
    string += ' :' + options.longParam;
  }
  if (irc.debug) console.log(string);
  irc._socket.write(string + '\r\n', callback);
};

irc.join = function (channel, callback) {
  irc.act({action: 'JOIN', params: [channel]}, callback);
};

irc.part = function (channel, msg, callback) {
  irc.act({action: 'PART', params: [channel, msg]}, callback);
};

irc.nick = function (nick, callback) {
  irc.act({action: 'NICK', params: [nick]}, callback);
};

irc.user = function (user, mode, realName, callback) {
  irc.act({action: 'USER', params: [user, mode, '*'],
          longParam: realName}, callback);
};

irc.quit = function (msg, callback) {
  irc.act({action: 'QUIT', params: [msg]}, function () {
    if (path.existsSync(lock_file))
      fs.unlinkSync(lock_file);
    callback();
    process.exit(0);
  });
};

irc._socket = net.connect(irc.config.port, irc.config.address, function () {
  var nick      = irc.config.nick;
  var user      = irc.config.user;
  var realName  = irc.config.realName;
  var chan      = irc.config.chan;

  irc.nick(nick, function () {
    irc.user(user, '8', realName, function () {
      var has_admin = false;
      for (var u in irc.users) {
        if (typeof irc.users[u] !== 'undefined')
          if (typeof irc.users[u].auth !== 'undefined')
            if (irc.users[u].auth === 'admin' || irc.users[u].auth === 'owner')
              has_admin = true;
      }
      if (!has_admin) {
        throw ("An admin must be configured in users.json!");
      }

      if (chan instanceof Array) {
        for (var i = 0, l = chan.length; i < l; i += 1) {
          irc.join(chan[i]);
        }
      } else {
        irc.join(chan);
      }
    });
  });
});

irc._socket.on('data', function (data) {
  data = data.toString();

  if (irc.debug) {
    console.log(data);
  }

  var params = data.split(' ');
  if (data[0] === ':') {
    // Chop off initial colon, send to emitter.
    // also chop off \r\n
    irc.emitter.emit(params[1], data.slice(1, -2));
  } else {
    irc.emitter.emit(params[0], data);
  }
});

irc.emitter.on('PING', function (data) {
  irc._socket.write('PONG ' + data.slice(data.indexOf(':')) + '\r\n');
});

irc.emitter.on('PRIVMSG', function (data) {

  // Look for first character of the message.
  if (data[data.indexOf(':') + 1] === irc.command_char) {
    var action = irc.splitcmd(data);
    if (irc.debug) console.log(action);
    irc.emitter.emit(action.cmd, action);
  }
});

global.irc = irc;
irc.plugins = [];
fs.readdir(plugin_dir, function (err, files) {
  for (var i = 0, len = files.length; i < len; i += 1) {
    var plugin = require(plugin_dir + files[i]);
    plugin.enabled = true;
    irc.plugins.push(plugin);
    irc.emitter.on(plugin.name, plugin.handler);
  }
});

irc.emitter.on('disable', function (act) {
  irc.check_level(act.nick, 'admin', function (is_admin) {
    if (is_admin) {
      for (var p in irc.plugins) {
        if (irc.plugins[p].name === act.params[0]) {
          irc.plugins[p].enabled = false;
          irc.emitter.removeListener(irc.plugins[p].name, irc.plugins[p].handler);
          irc.privmsg(act.source, act.params[0] + ' disabled');
        }
      }
    } else {
      irc.privmsg(act.source, 'ERROR: not authorized');
    }
  });
});

irc.emitter.on('enable', function (act) {
  irc.check_level(act.nick, 'admin', function (is_admin) {
    if (is_admin) {
      for (var p in irc.plugins) {
        if (irc.plugins[p].name === act.params[0] &&
            irc.plugins[p].enabled === false) {
          irc.plugins[p].enabled = true;
          irc.emitter.on(irc.plugins[p].name, irc.plugins[p].handler);
          irc.privmsg(act.source, act.params[0] + ' enabled');
        }
      }
    } else {
      irc.privmsg(act.source, 'ERROR: not authorized');
    }
  });
});

irc.emitter.on('set_auth', function (act) {
  var nick  = act.params[0];
  var level = act.params[1];
  var user  = irc.users[nick];

  if (typeof user === 'undefined')
    irc.users[nick] = {};

  if (act.params.length < 2) {
    irc.privmsg(act.source, 'ERROR: Insufficient parameters');
    return (1);
  }
  if (level !== 'user' && level !== 'owner' && level !== 'admin') {
    irc.privmsg(act.source, 'ERROR: Invalid parameter: ' + level);
    return (1);
  }
  irc.check_level(act.nick, 'owner', function (is_owner) {
    if (is_owner) {
      if (nick === act.nick) {
        irc.privmsg(act.source, 'ERROR: Cannot change your own permissions!');
      } else {
        user.auth = level;
        irc.privmsg(act.source, nick + ' made to ' + level);
      }
    } else {
      irc.privmsg(act.source, 'ERROR: Insufficient privileges');
    }
  });
});

irc.emitter.on('PRIVMSG', function (data) {
  var nick = data.slice(0, data.indexOf('!'));
  if (typeof irc.users[nick] === 'undefined') {
    irc.users[nick] = {};
  }
  if (data.split(' ')[2] !== irc.config.nick) {
    irc.users[nick].seen_time = new Date().toUTCString();
    irc.users[nick].seen_msg  = data.slice(data.indexOf(':') + 1);
    irc.users[nick].seen_channel = data.split(' ')[2];
  }
});

irc.emitter.on('seen', function (act) {
  var nick = act.params[0] ? act.params : act.nick;
  if (typeof irc.users[nick] === 'undefined' ||
      typeof irc.users[nick].seen_msg === 'undefined' ||
      typeof irc.users[nick].seen_time === 'undefined') {
    irc.privmsg(act.source, 'Unknown nick: ' + nick);
    return (1);
  }
  irc.privmsg(act.source, nick + ' last seen: ' + irc.users[nick].seen_time +
              " saying '" + irc.users[nick].seen_msg + "' in " +
              irc.users[nick].seen_channel);
});

<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Noise generator.
	 *          Uses looped noise buffers to save on performance.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string} type the noise type (white|pink|brown)
	 */
	Tone.Noise = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["type"], Tone.Noise.defaults);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  the buffer
		 *  @private
		 *  @type {AudioBuffer}
		 */
		this._buffer = null;

		/**
		 *  set a callback function to invoke when the sample is over
		 *
		 *  @type {function}
		 */
		this.onended = options.onended;

		this.setType(options.type);
	};

	Tone.extend(Tone.Noise, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Noise.defaults = {
		"type" : "white",
		"onended" : function(){}
	};

	/**
	 *  set the noise type
	 *
	 *  @param {string} type the noise type (white|pink|brown)
	 *  @param {Tone.Time} time (optional) time that the set will occur
	 */
	Tone.Noise.prototype.setType = function(type, time){
		switch (type){
			case "white" :
				this._buffer = _whiteNoise;
				break;
			case "pink" :
				this._buffer = _pinkNoise;
				break;
			case "brown" :
				this._buffer = _brownNoise;
				break;
			default :
				this._buffer = _whiteNoise;
		}
		//if it's playing, stop and restart it
		if (this.state === Tone.Source.State.STARTED){
			time = this.toSeconds(time);
			//remove the listener
			this._source.onended = undefined;
			this._stop(time);
			this._start(time);
		}
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Noise.prototype.set = function(params){
		if (!this.isUndef(params.type)) this.setType(params.type);
		if (!this.isUndef(params.onended)) this.onended = params.onended;
		Tone.Source.prototype.set.call(this, params);
	};

	/**
	 *  internal start method
	 *
	 *  @param {Tone.Time} time
	 *  @private
	 */
	Tone.Noise.prototype._start = function(time){
		this._source = this.context.createBufferSource();
		this._source.buffer = this._buffer;
		this._source.loop = true;
		this.chain(this._source, this.output);
		this._source.start(this.toSeconds(time));
		this._source.onended = this._onended.bind(this);
	};

	/**
	 *  start the noise at a specific time
	 *
	 *  @param {Tone.Time} time
	 */
	Tone.Noise.prototype.start = function(time){
		if (this.state === Tone.Source.State.STOPPED){
			this.state = Tone.Source.State.STARTED;
			//make the source
			this._start(time);
		}
	};

	/**
	 *  internal stop method
	 *
	 *  @param {Tone.Time} time
	 *  @private
	 */
	Tone.Noise.prototype._stop = function(time){
		this._source.stop(this.toSeconds(time));
	};

	/**
	 *  stop the noise at a specific time
	 *
	 *  @param {Tone.Time} time
	 */
	Tone.Noise.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED) {
			if (this._buffer && this._source){
				if (!time){
					this.state = Tone.Source.State.STOPPED;
				}
				this._stop(time);
			}
		}
	};

	/**
	 *  internal call when the buffer is done playing
	 *
	 *  @private
	 */
	Tone.Noise.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  dispose all the components
	 */
	Tone.Noise.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer = null;
	};

	///////////////////////////////////////////////////////////////////////////
	// THE BUFFERS
	// borred heavily from http://noisehack.com/generate-noise-web-audio-api/
	///////////////////////////////////////////////////////////////////////////

	/**
	 *	static noise buffers
	 *
	 *  @static
	 *  @private
	 *  @type {AudioBuffer}
	 */
	var _pinkNoise = null, _brownNoise = null, _whiteNoise = null;

	Tone._initAudioContext(function(audioContext){

		var sampleRate = audioContext.sampleRate;

		//four seconds per buffer
		var bufferLength = sampleRate * 4;

		//fill the buffers
		_pinkNoise = (function() {
			var buffer = audioContext.createBuffer(2, bufferLength, sampleRate);
			for (var channelNum = 0; channelNum < buffer.numberOfChannels; channelNum++){
				var channel = buffer.getChannelData(channelNum);
				var b0, b1, b2, b3, b4, b5, b6;
				b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;
				for (var i = 0; i < bufferLength; i++) {
					var white = Math.random() * 2 - 1;
					b0 = 0.99886 * b0 + white * 0.0555179;
					b1 = 0.99332 * b1 + white * 0.0750759;
					b2 = 0.96900 * b2 + white * 0.1538520;
					b3 = 0.86650 * b3 + white * 0.3104856;
					b4 = 0.55000 * b4 + white * 0.5329522;
					b5 = -0.7616 * b5 - white * 0.0168980;
					channel[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
					channel[i] *= 0.11; // (roughly) compensate for gain
					b6 = white * 0.115926;
				}
			}
			return buffer;
		}());

		_brownNoise = (function() {
			var buffer = audioContext.createBuffer(2, bufferLength, sampleRate);
			for (var channelNum = 0; channelNum < buffer.numberOfChannels; channelNum++){
				var channel = buffer.getChannelData(channelNum);
				var lastOut = 0.0;
				for (var i = 0; i < bufferLength; i++) {
					var white = Math.random() * 2 - 1;
					channel[i] = (lastOut + (0.02 * white)) / 1.02;
					lastOut = channel[i];
					channel[i] *= 3.5; // (roughly) compensate for gain
				}
			}
			return buffer;
		})();

		_whiteNoise = (function(){
			var buffer = audioContext.createBuffer(2, bufferLength, sampleRate);
			for (var channelNum = 0; channelNum < buffer.numberOfChannels; channelNum++){
				var channel = buffer.getChannelData(channelNum);
				for (var i = 0; i < bufferLength; i++){
					channel[i] =  Math.random() * 2 - 1;
				}
			}
			return buffer;
		}());
	});

	return Tone.Noise;
});<commit_msg>Noise getType method<commit_after>define(["Tone/core/Tone", "Tone/source/Source"], function(Tone){

	"use strict";

	/**
	 *  @class  Noise generator.
	 *          Uses looped noise buffers to save on performance.
	 *
	 *  @constructor
	 *  @extends {Tone.Source}
	 *  @param {string} type the noise type (white|pink|brown)
	 */
	Tone.Noise = function(){

		Tone.Source.call(this);
		var options = this.optionsObject(arguments, ["type"], Tone.Noise.defaults);

		/**
		 *  @private
		 *  @type {AudioBufferSourceNode}
		 */
		this._source = null;

		/**
		 *  the buffer
		 *  @private
		 *  @type {AudioBuffer}
		 */
		this._buffer = null;

		/**
		 *  set a callback function to invoke when the sample is over
		 *
		 *  @type {function}
		 */
		this.onended = options.onended;

		this.setType(options.type);
	};

	Tone.extend(Tone.Noise, Tone.Source);

	/**
	 *  the default parameters
	 *
	 *  @static
	 *  @const
	 *  @type {Object}
	 */
	Tone.Noise.defaults = {
		"type" : "white",
		"onended" : function(){}
	};

	/**
	 *  set the noise type
	 *
	 *  @param {string} type the noise type (white|pink|brown)
	 *  @param {Tone.Time} time (optional) time that the set will occur
	 */
	Tone.Noise.prototype.setType = function(type, time){
		switch (type){
			case "white" :
				this._buffer = _whiteNoise;
				break;
			case "pink" :
				this._buffer = _pinkNoise;
				break;
			case "brown" :
				this._buffer = _brownNoise;
				break;
			default :
				this._buffer = _whiteNoise;
		}
		//if it's playing, stop and restart it
		if (this.state === Tone.Source.State.STARTED){
			time = this.toSeconds(time);
			//remove the listener
			this._source.onended = undefined;
			this._stop(time);
			this._start(time);
		}
	};

	/**
	 *  get the type of noise
	 *  @return {string} the type of noise
	 */
	Tone.Noise.prototype.getType = function(){
		if (this._buffer === _whiteNoise){
			return "white";
		} else if (this._buffer === _brownNoise){
			return "brown";
		} else if (this._buffer === _pinkNoise){
			return "pink";
		}
	};

	/**
	 *  set the parameters at once
	 *  @param {Object} params
	 */
	Tone.Noise.prototype.set = function(params){
		if (!this.isUndef(params.type)) this.setType(params.type);
		if (!this.isUndef(params.onended)) this.onended = params.onended;
		Tone.Source.prototype.set.call(this, params);
	};

	/**
	 *  internal start method
	 *
	 *  @param {Tone.Time} time
	 *  @private
	 */
	Tone.Noise.prototype._start = function(time){
		this._source = this.context.createBufferSource();
		this._source.buffer = this._buffer;
		this._source.loop = true;
		this.chain(this._source, this.output);
		this._source.start(this.toSeconds(time));
		this._source.onended = this._onended.bind(this);
	};

	/**
	 *  start the noise at a specific time
	 *
	 *  @param {Tone.Time} time
	 */
	Tone.Noise.prototype.start = function(time){
		if (this.state === Tone.Source.State.STOPPED){
			this.state = Tone.Source.State.STARTED;
			//make the source
			this._start(time);
		}
	};

	/**
	 *  internal stop method
	 *
	 *  @param {Tone.Time} time
	 *  @private
	 */
	Tone.Noise.prototype._stop = function(time){
		this._source.stop(this.toSeconds(time));
	};

	/**
	 *  stop the noise at a specific time
	 *
	 *  @param {Tone.Time} time
	 */
	Tone.Noise.prototype.stop = function(time){
		if (this.state === Tone.Source.State.STARTED) {
			if (this._buffer && this._source){
				if (!time){
					this.state = Tone.Source.State.STOPPED;
				}
				this._stop(time);
			}
		}
	};

	/**
	 *  internal call when the buffer is done playing
	 *
	 *  @private
	 */
	Tone.Noise.prototype._onended = function(){
		this.state = Tone.Source.State.STOPPED;
		this.onended();
	};

	/**
	 *  dispose all the components
	 */
	Tone.Noise.prototype.dispose = function(){
		Tone.Source.prototype.dispose.call(this);
		if (this._source !== null){
			this._source.disconnect();
			this._source = null;
		}
		this._buffer = null;
	};

	///////////////////////////////////////////////////////////////////////////
	// THE BUFFERS
	// borred heavily from http://noisehack.com/generate-noise-web-audio-api/
	///////////////////////////////////////////////////////////////////////////

	/**
	 *	static noise buffers
	 *
	 *  @static
	 *  @private
	 *  @type {AudioBuffer}
	 */
	var _pinkNoise = null, _brownNoise = null, _whiteNoise = null;

	Tone._initAudioContext(function(audioContext){

		var sampleRate = audioContext.sampleRate;

		//four seconds per buffer
		var bufferLength = sampleRate * 4;

		//fill the buffers
		_pinkNoise = (function() {
			var buffer = audioContext.createBuffer(2, bufferLength, sampleRate);
			for (var channelNum = 0; channelNum < buffer.numberOfChannels; channelNum++){
				var channel = buffer.getChannelData(channelNum);
				var b0, b1, b2, b3, b4, b5, b6;
				b0 = b1 = b2 = b3 = b4 = b5 = b6 = 0.0;
				for (var i = 0; i < bufferLength; i++) {
					var white = Math.random() * 2 - 1;
					b0 = 0.99886 * b0 + white * 0.0555179;
					b1 = 0.99332 * b1 + white * 0.0750759;
					b2 = 0.96900 * b2 + white * 0.1538520;
					b3 = 0.86650 * b3 + white * 0.3104856;
					b4 = 0.55000 * b4 + white * 0.5329522;
					b5 = -0.7616 * b5 - white * 0.0168980;
					channel[i] = b0 + b1 + b2 + b3 + b4 + b5 + b6 + white * 0.5362;
					channel[i] *= 0.11; // (roughly) compensate for gain
					b6 = white * 0.115926;
				}
			}
			return buffer;
		}());

		_brownNoise = (function() {
			var buffer = audioContext.createBuffer(2, bufferLength, sampleRate);
			for (var channelNum = 0; channelNum < buffer.numberOfChannels; channelNum++){
				var channel = buffer.getChannelData(channelNum);
				var lastOut = 0.0;
				for (var i = 0; i < bufferLength; i++) {
					var white = Math.random() * 2 - 1;
					channel[i] = (lastOut + (0.02 * white)) / 1.02;
					lastOut = channel[i];
					channel[i] *= 3.5; // (roughly) compensate for gain
				}
			}
			return buffer;
		})();

		_whiteNoise = (function(){
			var buffer = audioContext.createBuffer(2, bufferLength, sampleRate);
			for (var channelNum = 0; channelNum < buffer.numberOfChannels; channelNum++){
				var channel = buffer.getChannelData(channelNum);
				for (var i = 0; i < bufferLength; i++){
					channel[i] =  Math.random() * 2 - 1;
				}
			}
			return buffer;
		}());
	});

	return Tone.Noise;
});<|endoftext|>


<commit_before>pipe.on('search::render', function render(pagelet) {
  'use strict';

  var placeholders = $(pagelet.placeholders);

  /**
   * Bypass the submit functionality and just redirect manually so we don't have
   * to do a server callback.
   *
   * @param {Event} e Optional event
   * @api private
   */
  function redirect(e) {
    if (e && e.preventDefault) e.preventDefault();

    //
    // Assume that the value in the $control_input is uptodate. If not get the
    // value directly through the constructor. When the selectize is still
    // loading results the `getValue()` will return an empty value. This is why
    // we do a double value check.
    //
    var selectize = select[0].selectize
      , value = selectize.$control_input.val() || selectize.getValue();

    if (!value) return;

    window.location = '/package/'+ value;
  }

  placeholders.find('form').submit(redirect);

  var select = placeholders.find('select[name="search"]').selectize({
    valueField: 'name',
    labelField: 'name',
    searchField: 'name',
    createOnBlur: true,
    create: true,

    /**
     * Load the autocomplete results through the Pagelet's RPC methods.
     *
     * @param {String} query Thing that we search for
     * @param {Function} callback Callback
     * @api private
     */
    load: function load(query, callback) {
      if (!query.length) return callback();

      pagelet.complete(query, function complete(err, results) {
        if (err) return callback();

        callback(results);
      });
    },

    render: {
      /**
       * Custom layout renderer for items.
       *
       * @param {Object} item The thing returned from the server.
       * @param {Function} escape Custom HTML escaper.
       * @returns {String}
       * @api private
       */
      option: function render(item, escape) {
        return [
          '
',
            ''+ escape(item.name) +'',
           'string' === typeof item.desc ? ''+ escape(item.desc) +'' : '',
          '
'
        ].join('');
      },

      /**
       * Return an empty string so we can remove the `do you want to create bla
       * bla bla` from the UI.
       *
       * @returns {String}
       * @api private
       */
      option_create: function create(data, escape) {
        return '';
      }
    },

    /**
     * Automatically submit form when item is clicked.
     *
     * @api private
     */
    onItemAdd: function itemadd() {
      setTimeout(redirect, 0);
    }
  });

  //
  // Make sure that the input is focused by default so we can immediately start
  // typing the package we want to search.
  //
  select[0].selectize.focus();

  //
  // Add an additional changes listener as the `selectize` library has no way to
  // hook in to the emitted keyup events. We want our form to submit as fast and
  // as soon possible so we're gonna allow people to press "enter" and submit
  // the current value that is their input/autocomplete field.
  //
  placeholders.on('keyup', 'form', function (e) {
    if (13 === e.which) redirect(e);
  });
});
<commit_msg>[migrate] Support bigpipe 0.6<commit_after>pipe.on('search:render', function render(pagelet) {
  'use strict';

  var placeholders = $(pagelet.placeholders);

  /**
   * Bypass the submit functionality and just redirect manually so we don't have
   * to do a server callback.
   *
   * @param {Event} e Optional event
   * @api private
   */
  function redirect(e) {
    if (e && e.preventDefault) e.preventDefault();

    //
    // Assume that the value in the $control_input is uptodate. If not get the
    // value directly through the constructor. When the selectize is still
    // loading results the `getValue()` will return an empty value. This is why
    // we do a double value check.
    //
    var selectize = select[0].selectize
      , value = selectize.$control_input.val() || selectize.getValue();

    if (!value) return;

    window.location = '/package/'+ value;
  }

  placeholders.find('form').submit(redirect);

  var select = placeholders.find('select[name="search"]').selectize({
    valueField: 'name',
    labelField: 'name',
    searchField: 'name',
    createOnBlur: true,
    create: true,

    /**
     * Load the autocomplete results through the Pagelet's RPC methods.
     *
     * @param {String} query Thing that we search for
     * @param {Function} callback Callback
     * @api private
     */
    load: function load(query, callback) {
      if (!query.length) return callback();

      pagelet.complete(query, function complete(err, results) {
        if (err) return callback();

        callback(results);
      });
    },

    render: {
      /**
       * Custom layout renderer for items.
       *
       * @param {Object} item The thing returned from the server.
       * @param {Function} escape Custom HTML escaper.
       * @returns {String}
       * @api private
       */
      option: function render(item, escape) {
        return [
          '
',
            ''+ escape(item.name) +'',
           'string' === typeof item.desc ? ''+ escape(item.desc) +'' : '',
          '
'
        ].join('');
      },

      /**
       * Return an empty string so we can remove the `do you want to create bla
       * bla bla` from the UI.
       *
       * @returns {String}
       * @api private
       */
      option_create: function create(data, escape) {
        return '';
      }
    },

    /**
     * Automatically submit form when item is clicked.
     *
     * @api private
     */
    onItemAdd: function itemadd() {
      setTimeout(redirect, 0);
    }
  });

  //
  // Make sure that the input is focused by default so we can immediately start
  // typing the package we want to search.
  //
  select[0].selectize.focus();

  //
  // Add an additional changes listener as the `selectize` library has no way to
  // hook in to the emitted keyup events. We want our form to submit as fast and
  // as soon possible so we're gonna allow people to press "enter" and submit
  // the current value that is their input/autocomplete field.
  //
  placeholders.on('keyup', 'form', function (e) {
    if (13 === e.which) redirect(e);
  });
});
<|endoftext|>


<commit_before>const highlightjs = require('highlight.js')
const marked = require('marked')
const remote = require('remote')
const ipc = require('ipc')

marked.setOptions({
  highlight: function (code, lang) {
    return highlightjs.highlightAuto(code, [ lang ]).value
  }
})

ipc.on('md', function (raw) {
  const md = marked(raw)
  const base = document.querySelector('base')
  const body = document.querySelector('.markdown-body')
  base.setAttribute('href', remote.getGlobal('baseUrl'))
  body.innerHTML = md
})

window.addEventListener('keydown', function (ev) {
  if (ev.keyCode === 27) remote.getCurrentWindow().close()
})

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

// menu
var vmdSubmenu = [
  { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click: function () { remote.require('app').quit() } }
]

if (process.platform === 'darwin') {
  vmdSubmenu = [
    { label: 'About vmd', selector: 'orderFrontStandardAboutPanel:' },
    { type: 'separator' }
  ].concat(vmdSubmenu)
}

var template = [
  {
    label: 'vmd',
    submenu: vmdSubmenu
  },
  {
    label: 'File',
    submenu: [
      { label: 'Print', accelerator: 'CmdOrCtrl+P', click: function () { window.print() } }
    ]
  },
  {
    label: 'View',
    submenu: [
      { label: 'Zoom In', accelerator: 'CmdOrCtrl+Plus', click: function () { zoom.zoomIn(); } },
      { label: 'Zoom Out', accelerator: 'CmdOrCtrl+-', click: function () { zoom.zoomOut(); } },
      { label: 'Reset Zoom', accelerator: 'CmdOrCtrl+0', click: function () { zoom.reset(); } }
    ]
  }
]

var Menu = remote.require('menu')
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
<commit_msg>remove some semilcolons :/<commit_after>const highlightjs = require('highlight.js')
const marked = require('marked')
const remote = require('remote')
const ipc = require('ipc')

marked.setOptions({
  highlight: function (code, lang) {
    return highlightjs.highlightAuto(code, [ lang ]).value
  }
})

ipc.on('md', function (raw) {
  const md = marked(raw)
  const base = document.querySelector('base')
  const body = document.querySelector('.markdown-body')
  base.setAttribute('href', remote.getGlobal('baseUrl'))
  body.innerHTML = md
})

window.addEventListener('keydown', function (ev) {
  if (ev.keyCode === 27) remote.getCurrentWindow().close()
})

var zoom = require('./zoom')()

// menu
var vmdSubmenu = [
  { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click: function () { remote.require('app').quit() } }
]

if (process.platform === 'darwin') {
  vmdSubmenu = [
    { label: 'About vmd', selector: 'orderFrontStandardAboutPanel:' },
    { type: 'separator' }
  ].concat(vmdSubmenu)
}

var template = [
  {
    label: 'vmd',
    submenu: vmdSubmenu
  },
  {
    label: 'File',
    submenu: [
      { label: 'Print', accelerator: 'CmdOrCtrl+P', click: function () { window.print() } }
    ]
  },
  {
    label: 'View',
    submenu: [
      { label: 'Zoom In', accelerator: 'CmdOrCtrl+Plus', click: function () { zoom.zoomIn() } },
      { label: 'Zoom Out', accelerator: 'CmdOrCtrl+-', click: function () { zoom.zoomOut() } },
      { label: 'Reset Zoom', accelerator: 'CmdOrCtrl+0', click: function () { zoom.reset() } }
    ]
  }
]

var Menu = remote.require('menu')
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
<|endoftext|>