<commit_before>// -*- Mode: JavaScript; tab-width: 4 -*- vim:tabstop=4 syntax=javascript:
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*jshint expr: true */
/*global module: false, randint: false */

module.version = 0.4;

module.adjs = ["acidic", "antique", "contemptible", "culturally-unsound",
	"despicable", "evil", "fermented", "festering", "foul", "fulminating", "humid", "impure",
	"inept", "inferior", "industrial", "left-over", "low-quality", "malodorous", "off-color",
	"penguin-molesting", "petrified", "pointy-nosed", "salty", "sausage-snorfling",
	"tasteless", "tempestuous", "tepid", "tofu-nibbling", "unintelligent", "unoriginal",
	"uninspiring", "weasel-smelling", "wretched", "spam-sucking", "egg-sucking",
	"decayed", "halfbaked", "infected", "squishy", "porous", "pickled", "coughed-up", "thick",
	"vapid", "hacked-up", "unmuzzled", "bawdy", "vain", "lumpish", "churlish", "fobbing",
	"rank", "craven", "puking", "jarring", "fly-bitten", "pox-marked", "fen-sucked", "spongy",
	"droning", "gleeking", "warped", "currish", "milk-livered", "surly", "mammering",
	"ill-borne", "beef-witted", "tickle-brained", "half-faced", "headless", "wayward",
	"rump-fed", "onion-eyed", "beslubbering", "villainous", "lewd-minded", "cockered",
	"full-gorged", "rude-snouted", "crook-pated", "pribbling", "dread-bolted", "fool-born",
	"puny", "fawning", "sheep-biting", "dankish", "goatish", "weather-bitten", "knotty-pated",
	"malt-wormy", "saucyspleened", "motley-mind", "it-fowling", "vassal-willed",
	"loggerheaded", "clapper-clawed", "frothy", "ruttish", "clouted", "common-kissing",
	"pignutted", "folly-fallen", "plume-plucked", "flap-mouthed", "swag-bellied",
	"dizzy-eyed", "gorbellied", "weedy", "reeky", "measled", "spur-galled", "mangled",
	"impertinent", "bootless", "toad-spotted", "hasty-witted", "horn-beat", "yeasty",
	"imp-bladdereddle-headed", "boil-brained", "tottering", "hedge-born",
	"hugger-muggered", "elf-skinned", "Microsoft-loving"];

module.amnts = ["accumulation", "bucket", "coagulation", "enema-bucketful",
	"gob", "half-mouthful", "heap", "mass", "mound", "petrification", "pile", "puddle", "stack",
	"thimbleful", "tongueful", "ooze", "quart", "bag", "plate", "ass-full", "assload"];

module.nouns = ["bat toenails", "bug spit", "cat hair", "chicken piss",
	"dog vomit", "dung", "fat woman's stomach-bile", "fish heads",
	"guano", "gunk", "pond scum", "rat retch", "red dye number-9",
	"Sun IPC manuals", "waffle-house grits", "yoo-hoo", "dog balls",
	"seagull puke", "cat bladders", "pus", "urine samples", "squirrel guts",
	"snake assholes", "snake bait", "buzzard gizzards", "cat-hair-balls",
	"rat-farts", "pods", "armadillo snouts", "entrails", "snake snot",
	"eel ooze", "slurpee-backwash", "toxic waste", "Stimpy-drool",
	"poopy", "poop", "craptacular carpet droppings", "jizzum",
	"cold sores", "anal warts", "IE user"];

// Comes up with a random insult. Copyedited from mozbot.
// https://mxr.mozilla.org/mozilla/source/webtools/mozbot/BotModules/Insult.bm
module.cmd_insult = function cmd_insult(dest, args, nick, ident, host, conn, relay) {
	switch (args.toLowerCase()) {
	case "yourself": case "self": case conn.nick:
		conn.reply(dest, nick, "Nice try fool.");
		return true;
	case "urself":
		conn.reply(dest, nick, "At least learn to spell.");
		return true;
	case "mozilla": case "firefox":
		conn.reply(dest, args, "You are nothing but the best browser on the planet.");
		return true;
	case "c++":
		conn.reply(dest, args, "You are evil.");
		return true;
	}

	//
	// Insults are formed by making combinations of:
	//
	//    You are nothing but a(n) {adj} {amt} of {adj} {noun}
	//
	var count = this.adjs.length, adj1 = this.adjs.random(), adj2;
	if (count > 1) {
		var index = randint(0, count);
		if (this.adjs[index] == adj1) { // musn't be the same as adj1
			index++;
			if (index >= count)
				index = 0;
		}
		adj2 = this.adjs[index];
	} else {
		adj2 = "err... of... some";
	}
	var amnt = this.amnts.random(), noun = this.nouns.random();
	var an = /^[aeiou]/.test(adj1) ? "an" : "a";
	conn.reply(dest, args && args != "me" ? args : nick,
	           "You are nothing but", an, adj1, amnt, "of", adj2, noun + ".");
	return true;
};

module.makeSlaps = function makeSlaps() {
	function me(msg) "\x01ACTION " + msg + "\x01";
	return [
		me("slaps $nick around a bit with a large trout"),
		me("slaps $nick around a bit with a small fish"),
		"$nick! Look over there! *slap*",
		me("gets the battering hammer and bashes $nick with it"),
		me("bashes $nick with a terrifying Windows ME user guide"),
		me("beats $nick to a pulp"),
		me("whams $nick into auscompgeek's Nokia"),
		me("hits $nick with an enormous Compaq laptop"),
		me("hits $nick with auscompgeek's DER-NSW Lenovo Edge 11"),
		me("hits $nick with a breath taking Windows ME user guide"),
		me("smacks $nick"),
		me("trips up $nick and laughs"),
		me("uses his 1337ness against $nick"),
		me("slaps $nick, therefore adding to his aggressiveness stats"),
		me("pokes $nick in the ribs"),
		me("drops a fully grown whale on $nick"),
		me("whacks $nick with a piece of someone's floorboard"),
		me("slaps $nick with IE6"),
		me("trout slaps $nick"),
		me("hits $nick over the head with a hammer"),
		me("slaps $nick"),
		me("slaps $nick with a trout"),
		me("whacks $nick with a suspicious brick"),
		me("puts $nick's fingers in a Chinese finger lock"),
		me("randomly slaps $nick"),
		me("pies $nick"),
		me("eats $nick"),
		me("teabags $nick"),
		me("hits $nick over the head with a 2-by-4"),
		me("drops a bowling bowl on $nick"),
		me("drops a large CRT monitor off a balcony above $nick")
	];
};
module.slaps = module.makeSlaps();

module.cmd_slap = function cmd_slap(dest, args, nick, ident, host, conn, relay) {
	conn.msg(dest, this.slaps.random().replace("$nick", args && args != conn.nick && args != "me" ? args : nick));
	return true;
};
<commit_msg>[meanie] make more sense<commit_after>// -*- Mode: JavaScript; tab-width: 4 -*- vim:tabstop=4 syntax=javascript:
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*jshint expr: true */
/*global module: false, randint: false */

module.version = 0.5;

module.adjs = ["acidic", "antique", "contemptible", "culturally-unsound",
	"despicable", "evil", "fermented", "festering", "foul", "fulminating", "humid", "impure",
	"inept", "inferior", "industrial", "left-over", "low-quality", "malodorous", "off-color",
	"penguin-molesting", "petrified", "pointy-nosed", "salty", "sausage-snorfling",
	"tasteless", "tempestuous", "tepid", "tofu-nibbling", "unintelligent", "unoriginal",
	"uninspiring", "weasel-smelling", "wretched", "spam-sucking", "egg-sucking",
	"decayed", "halfbaked", "infected", "squishy", "porous", "pickled", "coughed-up", "thick",
	"vapid", "hacked-up", "unmuzzled", "bawdy", "vain", "lumpish", "churlish", "fobbing",
	"rank", "craven", "puking", "jarring", "fly-bitten", "pox-marked", "fen-sucked", "spongy",
	"droning", "gleeking", "warped", "currish", "milk-livered", "surly", "mammering",
	"ill-borne", "beef-witted", "tickle-brained", "half-faced", "headless", "wayward",
	"rump-fed", "onion-eyed", "beslubbering", "villainous", "lewd-minded", "cockered",
	"full-gorged", "rude-snouted", "crook-pated", "pribbling", "dread-bolted", "fool-born",
	"puny", "fawning", "sheep-biting", "dankish", "goatish", "weather-bitten", "knotty-pated",
	"malt-wormy", "saucyspleened", "motley-mind", "it-fowling", "vassal-willed",
	"loggerheaded", "clapper-clawed", "frothy", "ruttish", "clouted", "common-kissing",
	"pignutted", "folly-fallen", "plume-plucked", "flap-mouthed", "swag-bellied",
	"dizzy-eyed", "gorbellied", "weedy", "reeky", "measled", "spur-galled", "mangled",
	"impertinent", "bootless", "toad-spotted", "hasty-witted", "horn-beat", "yeasty",
	"imp-bladdereddle-headed", "boil-brained", "tottering", "hedge-born",
	"hugger-muggered", "elf-skinned", "Microsoft-loving"];

module.amnts = ["accumulation", "bucket", "coagulation", "enema-bucketful",
	"gob", "half-mouthful", "heap", "mass", "mound", "petrification", "pile", "puddle", "stack",
	"thimbleful", "tongueful", "ooze", "quart", "bag", "plate", "ass-full", "assload"];

module.nouns = ["bat toenails", "bug spit", "cat hair", "chicken piss",
	"dog vomit", "dung", "fat woman's stomach-bile", "fish heads",
	"guano", "gunk", "pond scum", "rat retch", "red dye number-9",
	"Sun IPC manuals", "waffle-house grits", "yoo-hoo", "dog balls",
	"seagull puke", "cat bladders", "pus", "urine samples", "squirrel guts",
	"snake assholes", "snake bait", "buzzard gizzards", "cat-hair-balls",
	"rat-farts", "pods", "armadillo snouts", "entrails", "snake snot",
	"eel ooze", "slurpee-backwash", "toxic waste", "Stimpy-drool",
	"poopy", "poop", "craptacular carpet droppings", "jizzum",
	"cold sores", "anal warts", "IE user"];

// Comes up with a random insult. Copyedited from mozbot.
// https://mxr.mozilla.org/mozilla/source/webtools/mozbot/BotModules/Insult.bm
module.cmd_insult = function cmd_insult(dest, args, nick, ident, host, conn, relay) {
	switch (args.toLowerCase()) {
	case "yourself": case "itself": case "himself": case "herself": case "self": case conn.nick:
		conn.reply(dest, nick, "Nice try fool.");
		return true;
	case "urself": case "hisself":
		conn.reply(dest, nick, "At least learn to spell.");
		return true;
	case "mozilla": case "firefox":
		conn.reply(dest, args, "You are nothing but the best browser on the planet.");
		return true;
	case "c++":
		conn.reply(dest, args, "You are evil.");
		return true;
	}

	//
	// Insults are formed by making combinations of:
	//
	//    You are nothing but a(n) {adj} {amt} of {adj} {noun}
	//
	var count = this.adjs.length, adj1 = this.adjs.random(), adj2;
	if (count > 1) {
		var index = randint(0, count);
		if (this.adjs[index] == adj1) { // musn't be the same as adj1
			index++;
			if (index >= count)
				index = 0;
		}
		adj2 = this.adjs[index];
	} else {
		adj2 = "err... of... some";
	}
	var amnt = this.amnts.random(), noun = this.nouns.random();
	var an = /^[aeiou]/.test(adj1) ? "an" : "a";
	conn.reply(dest, args && args != "me" ? args : nick,
	           "You are nothing but", an, adj1, amnt, "of", adj2, noun + ".");
	return true;
};

module.makeSlaps = function makeSlaps() {
	function me(msg) "\x01ACTION " + msg + "\x01";
	return [
		me("slaps $nick around a bit with a large trout"),
		me("slaps $nick around a bit with a small fish"),
		"$nick! Look over there! *slap*",
		me("gets the battering hammer and bashes $nick with it"),
		me("bashes $nick with a terrifying Windows ME user guide"),
		me("beats $nick to a pulp"),
		me("whams auscompgeek's Nokia into $nick"),
		me("hits $nick with an enormous Compaq laptop"),
		me("hits $nick with auscompgeek's DER-NSW Lenovo Edge 11"),
		me("hits $nick with a breath taking Windows ME user guide"),
		me("smacks $nick"),
		me("trips up $nick and laughs"),
		me("uses his 1337ness against $nick"),
		me("slaps $nick, therefore adding to his aggressiveness stats"),
		me("pokes $nick in the ribs"),
		me("drops a fully grown whale on $nick"),
		me("whacks $nick with a piece of someone's floorboard"),
		me("slaps $nick with IE6"),
		me("trout slaps $nick"),
		me("hits $nick over the head with a hammer"),
		me("slaps $nick"),
		me("slaps $nick with a trout"),
		me("whacks $nick with a suspicious brick"),
		me("puts $nick's fingers in a Chinese finger lock"),
		me("randomly slaps $nick"),
		me("pies $nick"),
		me("eats $nick"),
		me("teabags $nick"),
		me("hits $nick over the head with a 2-by-4"),
		me("drops a bowling bowl on $nick"),
		me("drops a large CRT monitor off a balcony above $nick")
	];
};
module.slaps = module.makeSlaps();

module.cmd_slap = function cmd_slap(dest, args, nick, ident, host, conn, relay) {
	conn.msg(dest, this.slaps.random().replace("$nick", args && args != conn.nick && args != "me" ? args : nick));
	return true;
};
<|endoftext|>


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

const coap_types = [ "CON", "NON", "ACK", "RST" ];
const coap_methods = [ "EMPTY", "GET", "POST", "PUT", "DELETE" ];
const coap_options = {
  '1': 'If-Match',
  '3': 'Uri-Host',
  '4': 'ETag',
  '5': 'If-None-Match',
  '7': 'Uri-Port',
  '8': 'Location-Path',
  '11': 'Uri-Path',
  '12': 'Content-Format',
  '14': 'Max-Age',
  '15': 'Uri-Query',
  '17': 'Accept',
  '20': 'Location-Query',
  '35': 'Proxy-Uri',
  '39': 'Proxy-Scheme',
  '60': 'Size1'
};

function CoapMessage()
{
  if(!(this instanceof CoapMessage))
    return new CoapMessage();

  var ver, type, code, mid, token, payload, options;

  this.options = [];
}

module.exports = CoapMessage;

CoapMessage.prototype.get_codestring = function(code) {
  var class_ = (code & 0xe0) >>> 5;
  var detail = code & 0x1f;
  var ret = "";

  if(class_ == 0x00)
    ret = coap_methods[detail];
  else
    ret = util.format('%d.%02d', class_, detail);

  return ret;
};

CoapMessage.prototype.parse_option = function(buf, i, last_type) {
  var type = (buf[i] & 0xf0)>>>4;
  var len = buf[i] & 0x0f;
  i++;

  if(type == 13) type = buf[i++] + 13;
  else if(type == 14) {
    type = buf.readUInt16BE(i) + 269;
    i += 2;
  }

  if(len == 13) len = buf[i++] + 13;
  else if(type == 14) {
    type = buf.readUInt16BE(i) + 269;
    i += 2;
  }

  var opt = {};
  opt.type = type + last_type;
  opt.value = new Buffer(buf.slice(i, i+len));
  this.options.push(opt);

  return (i + opt.value.length);
};

CoapMessage.prototype.parse = function(packet) {
  var octet = packet[0];
  var len = packet.length;

  this.ver = (octet & 0xc0) >>> 6;
  this.type = (octet & 0x30) >> 4;
  this.code = packet.readUInt8(1);
  this.mid = packet.readUInt16BE(2);
  this.token = new Buffer(packet.slice(4, 4+(octet&0x0f)));

  // options & payload
  var i = this.token.length + 4;
  var last_type = 0;

  while(i < len) {
    if(packet[i] != 0xff) { // option(s)
      i = this.parse_option(packet, i, last_type);
      last_type = this.options[this.options.length-1].type;
    }
    else { // payload
      i++;
      var p_len = len - i;
      this.payload = new Buffer(packet.slice(i, i+p_len));
      i += p_len;
    }
  }
}

CoapMessage.prototype.packetize_optionvalue = function(type, value) {
  if(type == 'empty')
    return new Buffer(0);
  else if(type == 'uint') {
    if(value == 0)
      return new Buffer(0);
    else {
      var v = new Buffer(8),
          i = v.length;
      while(value != 0) {
        i--;
        s.writeUInt8(value%256, i);
        value = Math.floor(value/256);
      }
      return v.slice(i+1, v.length);
    }
  }
  else if(type == 'string')
    return new Buffer(value, 'utf-8');
  else { // opaque
    if(!(value instanceof Buffer))
      return new Buffer(value);
    else
      return value;
  }
}

CoapMessage.prototype.packetize_option = function(opt, last_type) {
  var buf = new Buffer(1500);
  var i = 0, octet = 0;
  var type = opt.type - last_type;
  var len = opt.value.length;

  if(type < 13) {
    octet |= (type << 4);
    type = 0;
  }
  else if(type < 269) {
    octet |= (13 << 4);
    type -= 13;
  }
  else {
    octet |= (14 << 4);
    type -= 269;
  }

  if(len < 13) {
    octet |= (len & 0x0f);
    len = 0;
  }
  else if(len < 269) {
    octet |= (13 & 0x0f);
    len -= 13;
  }
  else {
    octet |= (14 & 0x0f);
    len -= 269;
  }

  buf.writeUInt8(octet, i++);

  if(type > 12 && type < 256)
    buf.writeUInt8(type, i++);
  else if(type > 255) {
    buf.writeUInt16BE(type, i);
    i += 2;
  }

  if(len > 12 && len < 256)
    buf.writeUInt8(len, i++);
  else if(len > 255) {
    buf.writeUInt16BE(len, i);
    i += 2;
  }

  opt.value.copy(buf, i);
  i += opt.value.length;

  return new Buffer(buf.slice(0, i));
}

CoapMessage.prototype.packetize = function() {
  var buf = new Buffer(1500);
  var i = 0, last_type = 0;
  var octet = (this.ver << 6) | (this.type << 4);

  if(this.token != undefined)
    octet |= (this.token.length & 0x0f);

  buf.writeUInt8(octet, i++);
  buf.writeUInt8(this.code, i++);
  buf.writeUInt16BE(this.mid, i);
  i += 2;
  this.token.copy(buf, i);
  i += this.token.length;

  // option
  for(var j in this.options) {
    var o = this.packetize_option(this.options[j], last_type);
    o.copy(buf, i);
    i += o.length;
    last_type = this.options[j].type;
  }

  if(this.payload != undefined) {
    buf.writeUInt8(0xff, i++);
    this.payload.copy(buf, i);
    i += this.payload.length;
  }

  return new Buffer(buf.slice(0, i));
}

CoapMessage.prototype.toString = function() {
  if(this.ver == undefined)
    return '(undefined)';

  var obj = {
    'ver': this.ver,
    'type': coap_types[this.type],
    'code': this.get_codestring(this.code),
    'mid': this.mid.toString(16),
    'options': []
  };

  if(this.token != undefined)
    obj['token'] = this.token.toString('hex');

  for(var i in this.options) {
    obj['options'].push({
      'type': coap_options[this.options[i].type],
      'len': this.options[i].value.length,
      'val': this.options[i].value.toString('hex')
    });
  }

  if(this.payload != undefined)
    obj['payload'] = this.payload.toString('hex');

  return JSON.stringify(obj);
}
<commit_msg>change const to module vars<commit_after>var util = require('util');

function CoapMessage()
{
  if(!(this instanceof CoapMessage))
    return new CoapMessage();

  this.types = [ "CON", "NON", "ACK", "RST" ];
  this.methods = [ "EMPTY", "GET", "POST", "PUT", "DELETE" ];

  this.option_types = [];
  this.option_types[1]  = 'If-Match';
  this.option_types[3]  = 'Uri-Host';
  this.option_types[4]  = 'ETag';
  this.option_types[5]  = 'If-None-Match';
  this.option_types[7]  = 'Uri-Port';
  this.option_types[8]  = 'Location-Path';
  this.option_types[11] = 'Uri-Path';
  this.option_types[12] = 'Content-Format';
  this.option_types[14] = 'Max-Age';
  this.option_types[15] = 'Uri-Query';
  this.option_types[17] = 'Accept';
  this.option_types[20] = 'Location-Query';
  this.option_types[35] = 'Proxy-Uri';
  this.option_types[39] = 'Proxy-Scheme';
  this.option_types[60] = 'Size1';

  var ver, type, code, mid, token, payload;

  this.options = [];
}

module.exports = CoapMessage;

CoapMessage.prototype.get_codestring = function(code) {
  var class_ = (code & 0xe0) >>> 5;
  var detail = code & 0x1f;
  var ret = "";

  if(class_ == 0x00)
    ret = this.methods[detail];
  else
    ret = util.format('%d.%02d', class_, detail);

  return ret;
};

CoapMessage.prototype.parse_option = function(buf, i, last_type) {
  var type = (buf[i] & 0xf0)>>>4;
  var len = buf[i] & 0x0f;
  i++;

  if(type == 13) type = buf[i++] + 13;
  else if(type == 14) {
    type = buf.readUInt16BE(i) + 269;
    i += 2;
  }

  if(len == 13) len = buf[i++] + 13;
  else if(type == 14) {
    type = buf.readUInt16BE(i) + 269;
    i += 2;
  }

  var opt = {};
  opt.type = type + last_type;
  opt.value = new Buffer(buf.slice(i, i+len));
  this.options.push(opt);

  return (i + opt.value.length);
};

CoapMessage.prototype.parse = function(packet) {
  var octet = packet[0];
  var len = packet.length;

  this.ver = (octet & 0xc0) >>> 6;
  this.type = (octet & 0x30) >> 4;
  this.code = packet.readUInt8(1);
  this.mid = packet.readUInt16BE(2);
  this.token = new Buffer(packet.slice(4, 4+(octet&0x0f)));

  // options & payload
  var i = this.token.length + 4;
  var last_type = 0;

  while(i < len) {
    if(packet[i] != 0xff) { // option(s)
      i = this.parse_option(packet, i, last_type);
      last_type = this.options[this.options.length-1].type;
    }
    else { // payload
      i++;
      var p_len = len - i;
      this.payload = new Buffer(packet.slice(i, i+p_len));
      i += p_len;
    }
  }
}

CoapMessage.prototype.packetize_optionvalue = function(type, value) {
  if(type == 'empty')
    return new Buffer(0);
  else if(type == 'uint') {
    if(value == 0)
      return new Buffer(0);
    else {
      var v = new Buffer(8),
          i = v.length;
      while(value != 0) {
        i--;
        s.writeUInt8(value%256, i);
        value = Math.floor(value/256);
      }
      return v.slice(i+1, v.length);
    }
  }
  else if(type == 'string')
    return new Buffer(value, 'utf-8');
  else { // opaque
    if(!(value instanceof Buffer))
      return new Buffer(value);
    else
      return value;
  }
}

CoapMessage.prototype.packetize_option = function(opt, last_type) {
  var buf = new Buffer(1500);
  var i = 0, octet = 0;
  var type = opt.type - last_type;
  var len = opt.value.length;

  if(type < 13) {
    octet |= (type << 4);
    type = 0;
  }
  else if(type < 269) {
    octet |= (13 << 4);
    type -= 13;
  }
  else {
    octet |= (14 << 4);
    type -= 269;
  }

  if(len < 13) {
    octet |= (len & 0x0f);
    len = 0;
  }
  else if(len < 269) {
    octet |= (13 & 0x0f);
    len -= 13;
  }
  else {
    octet |= (14 & 0x0f);
    len -= 269;
  }

  buf.writeUInt8(octet, i++);

  if(type > 12 && type < 256)
    buf.writeUInt8(type, i++);
  else if(type > 255) {
    buf.writeUInt16BE(type, i);
    i += 2;
  }

  if(len > 12 && len < 256)
    buf.writeUInt8(len, i++);
  else if(len > 255) {
    buf.writeUInt16BE(len, i);
    i += 2;
  }

  opt.value.copy(buf, i);
  i += opt.value.length;

  return new Buffer(buf.slice(0, i));
}

CoapMessage.prototype.packetize = function() {
  var buf = new Buffer(1500);
  var i = 0, last_type = 0;
  var octet = (this.ver << 6) | (this.type << 4);

  if(this.token != undefined)
    octet |= (this.token.length & 0x0f);

  buf.writeUInt8(octet, i++);
  buf.writeUInt8(this.code, i++);
  buf.writeUInt16BE(this.mid, i);
  i += 2;
  this.token.copy(buf, i);
  i += this.token.length;

  // option
  for(var j in this.options) {
    var o = this.packetize_option(this.options[j], last_type);
    o.copy(buf, i);
    i += o.length;
    last_type = this.options[j].type;
  }

  if(this.payload != undefined) {
    buf.writeUInt8(0xff, i++);
    this.payload.copy(buf, i);
    i += this.payload.length;
  }

  return new Buffer(buf.slice(0, i));
}

CoapMessage.prototype.toString = function() {
  if(this.ver == undefined)
    return '(undefined)';

  var obj = {
    'ver': this.ver,
    'type': this.types[this.type],
    'code': this.get_codestring(this.code),
    'mid': this.mid.toString(16),
    'options': []
  };

  if(this.token != undefined)
    obj['token'] = this.token.toString('hex');

  for(var i in this.options) {
    obj['options'].push({
      'type': this.option_types[this.options[i].type],
      'len': this.options[i].value.length,
      'val': this.options[i].value.toString('hex')
    });
  }

  if(this.payload != undefined)
    obj['payload'] = this.payload.toString('hex');

  return JSON.stringify(obj);
}
<|endoftext|>


<commit_before>/* XML Methods for MooTools */

var XML = {

	rootFromFile: function(file){
		var root = null;
		switch (Browser.Engine.name){
			case 'webkit':
				var xmlhttp = new XMLHttpRequest();
				xmlhttp.open('GET', file, false);
				xmlhttp.send(null);
				return xmlhttp.responseXML;
			case 'trident': root = new ActiveXObject('Microsoft.XMLDOM');
			default: root = root || document.implementation.createDocument('', '', null);
		}

		root.async = false;
		root.load(file);
		return root;
	},

	rootFromString: function(string){
		var root;

		if (Browser.Engine.trident){
			root = new ActiveXObject('Microsoft.XMLDOM');
			root.async = false;
			root.loadXML(string);
		} else {
			root = new DOMParser().parseFromString(string, 'text/xml');
		}

		return root;
	},

	rootToHash: function(root){
		var hashes = [], children = root.childNodes;

		for (var i = 0, l = children.length; i < l; i++){
			var h = XML.nodeToHash(children[i]);
			if (h) hashes.push(h);
		}

		return hashes;
	},

	nodeToHash: function(node){
		switch ($type(node)){

			case 'element':
				var attributes = node.attributes;
				var attributesLength = attributes.length;

				var attributesHash = {};

				for (var j = 0; j < attributesLength; j++){
					var attribute = attributes[j];
					if (attribute.nodeValue && attribute.nodeValue != 'inherit') attributesHash[attribute.nodeName] = attribute.nodeValue;
				}

				return {tag: node.nodeName.toLowerCase(), attributes: attributesHash, children: XML.rootToHash(node)};

			case 'textnode': return {text: node.nodeValue};

			default: return null;
		}
	},

	hashesToTree: function(hash){
		var tree = [];
		for (var i = 0, l = hash.length; i < l; i++) tree.push(XML.hashToElement(hash[i]));
		return tree;
	},

	hashToElement: function(hash, tag){
		var element;
		if (hash.text) element = document.newTextNode(hash.text);
		else element = document.newElement(tag || hash.tag, hash.attributes).adopt(XML.hashesToTree(hash.children));
		return element;
	},

	transform: function(xml, xsl){
		xml = (typeof xml == 'string') ? XML.rootFromFile(xml) : xml;
		xsl = (typeof xsl == 'string') ? XML.rootFromFile(xsl) : xsl;

		var temp = document.newElement('div');

		if (Browser.Engine.trident){
			var html = xml.transformNode(xsl);
			temp.innerHTML = html;
		} else {
			var xslt = new XSLTProcessor();
			xslt.importStylesheet(xsl);
			var root = xslt.transformToFragment(xml, document);
			temp.appendChild(root);
		}

		var children = [];
		for (var i = 0, l = temp.childNodes.length; i < l; i++){
			var element = temp.childNodes[i], type = $type(element);
			if (type == 'element' || type == 'textnode') children.push(element);
		}
		return children;
	}

};
<commit_msg> - added hash->html_string transformation  - renamed rootToHash to rootToHashes  - code is still pretty raw :)<commit_after>/* XML Methods for MooTools */
/* Requires MooTools v1.2 */

var XML = {

	rootFromFile: function(file){
		var root = null;
		switch (Browser.Engine.name){
			case 'webkit':
				var xmlhttp = new XMLHttpRequest();
				xmlhttp.open('GET', file, false);
				xmlhttp.send(null);
				return xmlhttp.responseXML;
			case 'trident': root = new ActiveXObject('Microsoft.XMLDOM');
			default: root = root || document.implementation.createDocument('', '', null);
		}

		root.async = false;
		root.load(file);
		return root;
	},

	rootFromString: function(string){
		var root;

		if (Browser.Engine.trident){
			root = new ActiveXObject('Microsoft.XMLDOM');
			root.async = false;
			root.loadXML(string);
		} else {
			root = new DOMParser().parseFromString(string, 'text/xml');
		}

		return root;
	},

	rootToHashes: function(root){
		var hashes = [], children = root.childNodes;

		for (var i = 0, l = children.length; i < l; i++){
			var hash = XML.nodeToHash(children[i]);
			if (hash) hashes.push(hash);
		}

		return hashes;
	},

	nodeToHash: function(node){
		switch ($type(node)){

			case 'element':
				var attributes = node.attributes;
				var attributesLength = attributes.length;

				var attributesHash = {};

				for (var j = 0; j < attributesLength; j++){
					var attribute = attributes[j];
					if (attribute.nodeValue && attribute.nodeValue != 'inherit') attributesHash[attribute.nodeName] = attribute.nodeValue;
				}

				return {tag: node.nodeName.toLowerCase(), attributes: attributesHash, children: XML.rootToHashes(node)};

			case 'textnode': return {text: node.nodeValue};

			default: return null;
		}
	},

	hashesToTree: function(hash){
		var tree = [];
		for (var i = 0, l = hash.length; i < l; i++) tree.push(XML.hashToElement(hash[i]));
		return tree;
	},

	hashToElement: function(hash, tag){
		var element;
		if (hash.text) element = document.newTextNode(hash.text);
		else element = document.newElement(tag || hash.tag, hash.attributes).adopt(XML.hashesToTree(hash.children));
		return element;
	},

	hashToHTML: function(hash, level){
		var tabs = new Array(level || 0).join('\t');
		if (hash.text) return tabs + hash.text;
		var attributes = [''];
		for (var p in hash.attributes) attributes.push(p + '="' + hash.attributes[p] + '"');
		attributes = attributes.join(' ');
		var open = tabs + '<' + hash.tag + attributes + '>\n';
		var close = '\n' + tabs + '</' + hash.tag + '>';
		var children = XML.hashesToHTML(hash.children, level + 1);
		return open + children + close;
	},

	hashesToHTML: function(hashes, level){
		var html = [];
		for (var i = 0, l = hashes.length; i < l; i++) html.push(XML.hashToHTML(hashes[i], level));
		return html.join('\n');
	},

	transform: function(xml, xsl){
		xml = (typeof xml == 'string') ? XML.rootFromFile(xml) : xml;
		xsl = (typeof xsl == 'string') ? XML.rootFromFile(xsl) : xsl;

		var temp = document.newElement('div');

		if (Browser.Engine.trident){
			var html = xml.transformNode(xsl);
			temp.innerHTML = html;
		} else {
			var xslt = new XSLTProcessor();
			xslt.importStylesheet(xsl);
			var root = xslt.transformToFragment(xml, document);
			temp.appendChild(root);
		}

		var children = [];
		for (var i = 0, l = temp.childNodes.length; i < l; i++){
			var element = temp.childNodes[i], type = $type(element);
			if (type == 'element' || type == 'textnode') children.push(element);
		}
		return children;
	}

};
<|endoftext|>


<commit_before>"use strict";

var reportsServer = "http://localhost:5000/upload";
var productName = "TrackingProtection";
// FIXME get this from the addon
var version = "0.0.2";

function submitReport(comments, url, screenshot) {
    var serverURL = reportsServer;
    var xhr = new XMLHttpRequest();

    var form = {
        "ProductName": productName,
        "Version": version,
        "Comments": comments,
        "URL": url,
    };
    if (screenshot && document.getElementById("screenshot").checked) {
        form["screenshot"] = screenshot;
    }

    xhr.open("POST", serverURL, true);
    var boundary=Math.random().toString().substr(2);
    xhr.setRequestHeader("content-type",
        "multipart/form-data; charset=utf-8; boundary=" + boundary);

    var multipart = "";
    for (var key in form) {
        multipart += "--" + boundary +
            "\r\nContent-Disposition: form-data; name=\"" + key + "\"" +
            "\r\nContent-type: text/plain" +
            "\r\n\r\n" + form[key] + "\r\n";
    }
    multipart += "--" + boundary + "--\r\n";

    var status = document.getElementById("status");
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
          if (xhr.status == 200) {
            console.log("report id:", xhr.responseText);
            status.textContent = "report sent, thanks!";
            var textarea = document.getElementById("report-content");
            textarea.value = "";
          } else {
            status.textContent = "error submitting report, please try again.";
          }
        }
    };
    xhr.send(multipart);
    status.textContent = "sending report...";
}

document.getElementById("report").addEventListener("click", evt => {
  // FIXME test
  let comments = document.getElementById("report-content").value;
  let url = window.opener.gBrowser.currentURI.spec;
  let screenshot = "test123";
  submitReport(comments, url, screenshot);
});
<commit_msg>fix comment<commit_after>"use strict";

var reportsServer = "http://localhost:5000/upload";
var productName = "TrackingProtection";
// FIXME get this from the addon
var version = "0.0.2";

function submitReport(comments, url, screenshot) {
    var serverURL = reportsServer;
    var xhr = new XMLHttpRequest();

    var form = {
        "ProductName": productName,
        "Version": version,
        "Comments": comments,
        "URL": url,
    };
    if (screenshot && document.getElementById("screenshot").checked) {
        form["screenshot"] = screenshot;
    }

    xhr.open("POST", serverURL, true);
    var boundary=Math.random().toString().substr(2);
    xhr.setRequestHeader("content-type",
        "multipart/form-data; charset=utf-8; boundary=" + boundary);

    var multipart = "";
    for (var key in form) {
        multipart += "--" + boundary +
            "\r\nContent-Disposition: form-data; name=\"" + key + "\"" +
            "\r\nContent-type: text/plain" +
            "\r\n\r\n" + form[key] + "\r\n";
    }
    multipart += "--" + boundary + "--\r\n";

    var status = document.getElementById("status");
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
          if (xhr.status == 200) {
            console.log("report id:", xhr.responseText);
            status.textContent = "report sent, thanks!";
            var textarea = document.getElementById("report-content");
            textarea.value = "";
          } else {
            status.textContent = "error submitting report, please try again.";
          }
        }
    };
    xhr.send(multipart);
    status.textContent = "sending report...";
}

document.getElementById("report").addEventListener("click", evt => {
  let comments = document.getElementById("report-content").value;
  let url = window.opener.gBrowser.currentURI.spec;
  // FIXME probably need to use frame script to get this
  let screenshot = "test123";
  submitReport(comments, url, screenshot);
});
<|endoftext|>


<commit_before>/* globals UITour */
/** The main module is loaded on startup

This also contains the UI that is directly in the browser,
specifically the button and control over the panel.  `lib/errors.js`
controls some error-specific UI
*/

"use strict";
// cfx set this to true, and causes a ton of messages
require("sdk/preferences/service").set("javascript.options.strict", false);

const self = require("sdk/self");
const tabs = require("sdk/tabs");
const shooter = require("./shooter");
const { prefs } = require("sdk/simple-prefs");
const helperworker = require("./helperworker");
const { ActionButton } = require("sdk/ui/button/action");
const { watchFunction } = require("./errors");
const { Cu, Cc, Ci } = require("chrome");
const winutil = require("sdk/window/utils");
const req = require("./req");
const { setTimeout } = require("sdk/timers");
var { Hotkey } = require("sdk/hotkeys");

let Services;

// Give the server a chance to start if the pref is set
require("./headless").init();

Cu.import("resource:///modules/UITour.jsm");

let loadReason = null; // eslint-disable-line no-unused-vars
let initialized = false;
let tabsBeingShot = {};

function getNotificationBox(browser) {
  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
  let win = wm.getMostRecentWindow("navigator:browser");
  let gBrowser = win.gBrowser;

  browser = browser || gBrowser.selectedBrowser;
  return gBrowser.getNotificationBox(browser);
}

function showNotificationBar(shotcontext) {
  var nb = require("./notificationbox");
  if (nb.notificationbox().getNotificationWithValue("pageshot-notification-bar") !== null) {
    return;
  }
  let thebox = nb.notificationbox();
  let fragment = thebox.ownerDocument.createDocumentFragment();
  let myShots = thebox.ownerDocument.createElement("button");
  myShots.className = "myshots";
  myShots.setAttribute("label", "myshots");
  let preMyShots = thebox.ownerDocument.createElement("span");
  preMyShots.className = "pre-myshots";
  myShots.appendChild(preMyShots);
  let myShotsText = thebox.ownerDocument.createElement("span");
  myShotsText.className = "myshots-text";
  myShotsText.textContent = "My Shots";
  myShots.appendChild(myShotsText);
  let postMyShots = thebox.ownerDocument.createElement("span");
  postMyShots.className = "post-myshots";
  myShots.appendChild(postMyShots);
  myShots.className = "myshots";
  myShots.onclick = watchFunction(exports.openMyShots);
  let messageNode = thebox.ownerDocument.createElement("span");
  messageNode.style.border = "none";
  messageNode.style.marginLeft = "10px";
  messageNode.style.fontWeight = "normal";
  messageNode.appendChild(thebox.ownerDocument.createTextNode("Select part of the page to save:"));
  // FIXME Remove the myShots code once we're sure we won't want it any more
  //fragment.appendChild(myShots);
  fragment.appendChild(messageNode);
  nb.banner({
    id: "pageshot-notification-bar",
    msg: fragment,
    callback: function (message) {
      // Only message should be AlertClose
      if (message !== "removed") {
        console.warn("Unexpected message on notificationbox:", message);
        return;
      }
      shotcontext.destroy();
    },
    buttons: [
      nb.buttonMaker.yes({
        label: "Save",
        callback: function(notebox, button) {
          hideNotificationBar();
          setTimeout(function () {
            shotcontext.takeShot();
          }, 0);
        }
      }),
      nb.buttonMaker.no({
        label: "Cancel",
        callback: function(notebox, button) {
          hideNotificationBar();
          setTimeout(function () {
            shotcontext.destroy();
          }, 0);
        }
      })
    ]
  });

  setSaveButtonText("Save", true);

  if (!initialized) {
    if (! Services) {
      let importer = {};
      Cu.import("resource://gre/modules/Services.jsm", importer);
      Services = importer.Services;
    }

    initialized = true;
    // Load our stylesheets.
    let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);

    let cssurl = self.data.url("pageshot-notification-bar.css");

    let styleSheetURI = Services.io.newURI(cssurl, null, null);
    styleSheetService.loadAndRegisterSheet(styleSheetURI,
                                           styleSheetService.AUTHOR_SHEET);
  }
}

function hideNotificationBar(browser) {
  let box = getNotificationBox(browser);
  let notification = box.getNotificationWithValue("pageshot-notification-bar");
  let removed = false;
  if (notification) {
    box.removeNotification(notification);
    removed = true;
  }
  return removed;
}

exports.openMyShots = function () {
  if (! prefs.hasUsedMyShots) {
    prefs.hasUsedMyShots = true;
  }
  hideNotificationBar();
  setTimeout(() => {
    tabs.open(exports.getBackend() + "/shots");
  });
};

exports.showSaveFullPage = function () {
  setSaveButtonText("Save Full Page");
};

exports.showSave = function () {
  setSaveButtonText("Save", false);
};

function setSaveButtonText(text, disabled) {
  let box = getNotificationBox();
  let notification = box.getNotificationWithValue("pageshot-notification-bar");
  let els = notification.getElementsByTagName("*");
  for (let i=0; i<els.length; i++) {
    console.log("checking element", els[i].tagName, els[i].outerHTML);
    if (els[i].tagName == "button" && els[i].className.indexOf("notification-button-default") != -1) {
      if (disabled === true || disabled === false) {
        els[i].setAttribute("disabled", disabled);
      }
      els[i].setAttribute("label", text);
      console.log("did it!");
      break;
    }
  }
}

exports.hideNotificationBar = hideNotificationBar;

function showTopbar(shotContext) {
  let box = getNotificationBox();
  let notification = box.getNotificationWithValue("pageshot-notification-bar");
  if (!notification) {
    hideInfoPanel();
    showNotificationBar(shotContext);
    req.sendEvent("addon", "overlay-ui");
  }
}

exports.showTopbar = showTopbar;

function takeShot(source) {
  let thisTabId = tabs.activeTab.id;
  if (tabsBeingShot[thisTabId] !== true) {
    tabsBeingShot[thisTabId] = true;
    let shotContext = shooter.ShotContext(exports.getBackend(), () => {
      delete tabsBeingShot[thisTabId];
    });
    req.sendEvent("start-shot", source);
  } else {
    req.sendEvent("aborted-start-shot", "toolbar-pageshot-button");
    console.warn("Tried to take a shot while a shot was already in progress.");
  }
}

var hotKey = Hotkey({
  combo: "accel-alt-control-c",
  onPress: function() {
    takeShot("keyboard-shortcut");
  }
});

var shootButton = ActionButton({
  id: "pageshot-shooter",
  label: "Make shot",
  icon: self.data.url("icons/pageshot.svg"),
  onClick: watchFunction(function () {
    takeShot("toolbar-pageshot-button");
  })
});
exports.shootButton = shootButton;

/** We use backendOverride to temporarily change the backend with a
    command-line argument (as used in the `run` script), otherwise
    falls back to the addon pref */
var backendOverride = null;

exports.getBackend = function () {
  return backendOverride || prefs.backend;
};

let infoPanelShownForWindow = null;

exports.showInfoPanel = function showInfoPanel(magicCookie, title, description) {
  /*let win = winutil.getMostRecentBrowserWindow();
  let target = {
    node: win.document.getElementById(magicCookie),
    targetName: magicCookie
  };
  UITour.showInfo(win, null, target, title, description);
  UITour.showHighlight(win, target, "wobble");
  infoPanelShownForWindow = win;*/
};

function showTour(newTab) {
  let helpurl = exports.getBackend() + "/homepage/help.html";
  let win = winutil.getMostRecentBrowserWindow();
  if (newTab) {
    shooter.showTourOnNextLinkClick();
    tabs.open(helpurl);
    let newtab = tabs[tabs.length - 1];
    newtab.on("close", hideInfoPanel);
    newtab.on("deactivate", hideInfoPanel);
  } else {
    win.loadURI(helpurl);
  }
  exports.showInfoPanel(
    "toggle-button--jid1-neeaf3sahdkhpajetpack-pageshot-shooter",
    "Welcome to PageShot",
    "Click the camera button to clip a part of the page");
}

function hideInfoPanel() {
  if (infoPanelShownForWindow) {
    UITour.hideInfo(infoPanelShownForWindow);
    UITour.hideHighlight(infoPanelShownForWindow);
    infoPanelShownForWindow = null;
  }
}

// For reasons see https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Listening_for_load_and_unload
exports.main = function (options) {
  loadReason = options.loadReason;
  if (options.loadReason === "install") {
    req.sendEvent("install");
    showTour();
  }
  helperworker.trackMods(backendOverride || null);
  require("./user").initialize(exports.getBackend(), options.loadReason).catch((error) => {
    console.warn("Failed to log in to server:", exports.getBackend(), error+"");
  });
};

exports.onUnload = function (reason) {
  if (reason == "shutdown") {
    return;
  }
  req.sendEvent("uninstall");
  hideNotificationBar();
  console.info("Unloading PageShot framescripts");
  require("./framescripter").unload();
  console.info("Informing site of unload reason:", reason);
  let deviceInfo = require("./deviceinfo").deviceInfo();
  require("./req").request(exports.getBackend() + "/api/unload", {
    ignoreLogin: true,
    method: "post",
    contentType: "application/x-www-form-urlencoded",
    content: {
      reason,
      deviceInfo: JSON.stringify(deviceInfo)
    }
  });
  // We can't rely on the server removing cookies, because the request may not
  // complete locally, since the addon is being destroyed
  removeCookies();
};

/** Remove the user and user.sig cookies for the backend */
function removeCookies() {
  let namespace = {};
  Cu.import('resource://gre/modules/Services.jsm', namespace);
  let domain = require("sdk/url").URL(exports.getBackend()).hostname;
  namespace.Services.cookies.add(domain, "/", "user", "", false, false, false, 0);
  namespace.Services.cookies.add(domain, "/", "user.sig", "", false, false, false, 0);
}
<commit_msg>Don't try to do the tour or send events until after initialization has been successful<commit_after>/* globals UITour */
/** The main module is loaded on startup

This also contains the UI that is directly in the browser,
specifically the button and control over the panel.  `lib/errors.js`
controls some error-specific UI
*/

"use strict";
// cfx set this to true, and causes a ton of messages
require("sdk/preferences/service").set("javascript.options.strict", false);

const self = require("sdk/self");
const tabs = require("sdk/tabs");
const shooter = require("./shooter");
const { prefs } = require("sdk/simple-prefs");
const helperworker = require("./helperworker");
const { ActionButton } = require("sdk/ui/button/action");
const { watchFunction } = require("./errors");
const { Cu, Cc, Ci } = require("chrome");
const winutil = require("sdk/window/utils");
const req = require("./req");
const { setTimeout } = require("sdk/timers");
var { Hotkey } = require("sdk/hotkeys");

let Services;

// Give the server a chance to start if the pref is set
require("./headless").init();

Cu.import("resource:///modules/UITour.jsm");

let loadReason = null; // eslint-disable-line no-unused-vars
let initialized = false;
let tabsBeingShot = {};

function getNotificationBox(browser) {
  let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
  let win = wm.getMostRecentWindow("navigator:browser");
  let gBrowser = win.gBrowser;

  browser = browser || gBrowser.selectedBrowser;
  return gBrowser.getNotificationBox(browser);
}

function showNotificationBar(shotcontext) {
  var nb = require("./notificationbox");
  if (nb.notificationbox().getNotificationWithValue("pageshot-notification-bar") !== null) {
    return;
  }
  let thebox = nb.notificationbox();
  let fragment = thebox.ownerDocument.createDocumentFragment();
  let myShots = thebox.ownerDocument.createElement("button");
  myShots.className = "myshots";
  myShots.setAttribute("label", "myshots");
  let preMyShots = thebox.ownerDocument.createElement("span");
  preMyShots.className = "pre-myshots";
  myShots.appendChild(preMyShots);
  let myShotsText = thebox.ownerDocument.createElement("span");
  myShotsText.className = "myshots-text";
  myShotsText.textContent = "My Shots";
  myShots.appendChild(myShotsText);
  let postMyShots = thebox.ownerDocument.createElement("span");
  postMyShots.className = "post-myshots";
  myShots.appendChild(postMyShots);
  myShots.className = "myshots";
  myShots.onclick = watchFunction(exports.openMyShots);
  let messageNode = thebox.ownerDocument.createElement("span");
  messageNode.style.border = "none";
  messageNode.style.marginLeft = "10px";
  messageNode.style.fontWeight = "normal";
  messageNode.appendChild(thebox.ownerDocument.createTextNode("Select part of the page to save:"));
  // FIXME Remove the myShots code once we're sure we won't want it any more
  //fragment.appendChild(myShots);
  fragment.appendChild(messageNode);
  nb.banner({
    id: "pageshot-notification-bar",
    msg: fragment,
    callback: function (message) {
      // Only message should be AlertClose
      if (message !== "removed") {
        console.warn("Unexpected message on notificationbox:", message);
        return;
      }
      shotcontext.destroy();
    },
    buttons: [
      nb.buttonMaker.yes({
        label: "Save",
        callback: function(notebox, button) {
          hideNotificationBar();
          setTimeout(function () {
            shotcontext.takeShot();
          }, 0);
        }
      }),
      nb.buttonMaker.no({
        label: "Cancel",
        callback: function(notebox, button) {
          hideNotificationBar();
          setTimeout(function () {
            shotcontext.destroy();
          }, 0);
        }
      })
    ]
  });

  setSaveButtonText("Save", true);

  if (!initialized) {
    if (! Services) {
      let importer = {};
      Cu.import("resource://gre/modules/Services.jsm", importer);
      Services = importer.Services;
    }

    initialized = true;
    // Load our stylesheets.
    let styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);

    let cssurl = self.data.url("pageshot-notification-bar.css");

    let styleSheetURI = Services.io.newURI(cssurl, null, null);
    styleSheetService.loadAndRegisterSheet(styleSheetURI,
                                           styleSheetService.AUTHOR_SHEET);
  }
}

function hideNotificationBar(browser) {
  let box = getNotificationBox(browser);
  let notification = box.getNotificationWithValue("pageshot-notification-bar");
  let removed = false;
  if (notification) {
    box.removeNotification(notification);
    removed = true;
  }
  return removed;
}

exports.openMyShots = function () {
  if (! prefs.hasUsedMyShots) {
    prefs.hasUsedMyShots = true;
  }
  hideNotificationBar();
  setTimeout(() => {
    tabs.open(exports.getBackend() + "/shots");
  });
};

exports.showSaveFullPage = function () {
  setSaveButtonText("Save Full Page");
};

exports.showSave = function () {
  setSaveButtonText("Save", false);
};

function setSaveButtonText(text, disabled) {
  let box = getNotificationBox();
  let notification = box.getNotificationWithValue("pageshot-notification-bar");
  let els = notification.getElementsByTagName("*");
  for (let i=0; i<els.length; i++) {
    console.log("checking element", els[i].tagName, els[i].outerHTML);
    if (els[i].tagName == "button" && els[i].className.indexOf("notification-button-default") != -1) {
      if (disabled === true || disabled === false) {
        els[i].setAttribute("disabled", disabled);
      }
      els[i].setAttribute("label", text);
      console.log("did it!");
      break;
    }
  }
}

exports.hideNotificationBar = hideNotificationBar;

function showTopbar(shotContext) {
  let box = getNotificationBox();
  let notification = box.getNotificationWithValue("pageshot-notification-bar");
  if (!notification) {
    hideInfoPanel();
    showNotificationBar(shotContext);
    req.sendEvent("addon", "overlay-ui");
  }
}

exports.showTopbar = showTopbar;

function takeShot(source) {
  let thisTabId = tabs.activeTab.id;
  if (tabsBeingShot[thisTabId] !== true) {
    tabsBeingShot[thisTabId] = true;
    let shotContext = shooter.ShotContext(exports.getBackend(), () => {
      delete tabsBeingShot[thisTabId];
    });
    req.sendEvent("start-shot", source);
  } else {
    req.sendEvent("aborted-start-shot", "toolbar-pageshot-button");
    console.warn("Tried to take a shot while a shot was already in progress.");
  }
}

var hotKey = Hotkey({
  combo: "accel-alt-control-c",
  onPress: function() {
    takeShot("keyboard-shortcut");
  }
});

var shootButton = ActionButton({
  id: "pageshot-shooter",
  label: "Make shot",
  icon: self.data.url("icons/pageshot.svg"),
  onClick: watchFunction(function () {
    takeShot("toolbar-pageshot-button");
  })
});
exports.shootButton = shootButton;

/** We use backendOverride to temporarily change the backend with a
    command-line argument (as used in the `run` script), otherwise
    falls back to the addon pref */
var backendOverride = null;

exports.getBackend = function () {
  return backendOverride || prefs.backend;
};

let infoPanelShownForWindow = null;

exports.showInfoPanel = function showInfoPanel(magicCookie, title, description) {
  /*let win = winutil.getMostRecentBrowserWindow();
  let target = {
    node: win.document.getElementById(magicCookie),
    targetName: magicCookie
  };
  UITour.showInfo(win, null, target, title, description);
  UITour.showHighlight(win, target, "wobble");
  infoPanelShownForWindow = win;*/
};

function showTour(newTab) {
  let helpurl = exports.getBackend() + "/homepage/help.html";
  let win = winutil.getMostRecentBrowserWindow();
  if (newTab) {
    shooter.showTourOnNextLinkClick();
    tabs.open(helpurl);
    let newtab = tabs[tabs.length - 1];
    newtab.on("close", hideInfoPanel);
    newtab.on("deactivate", hideInfoPanel);
  } else {
    win.loadURI(helpurl);
  }
  exports.showInfoPanel(
    "toggle-button--jid1-neeaf3sahdkhpajetpack-pageshot-shooter",
    "Welcome to PageShot",
    "Click the camera button to clip a part of the page");
}

function hideInfoPanel() {
  if (infoPanelShownForWindow) {
    UITour.hideInfo(infoPanelShownForWindow);
    UITour.hideHighlight(infoPanelShownForWindow);
    infoPanelShownForWindow = null;
  }
}

// For reasons see https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Listening_for_load_and_unload
exports.main = function (options) {
  loadReason = options.loadReason;
  helperworker.trackMods(backendOverride || null);
  require("./user").initialize(exports.getBackend(), options.loadReason).then(() => {
    if (options.loadReason === "install") {
      req.sendEvent("install");
      showTour();
    }
  }).catch((error) => {
    console.warn("Failed to log in to server:", exports.getBackend(), error+"");
  });
};

exports.onUnload = function (reason) {
  if (reason == "shutdown") {
    return;
  }
  req.sendEvent("uninstall");
  hideNotificationBar();
  console.info("Unloading PageShot framescripts");
  require("./framescripter").unload();
  console.info("Informing site of unload reason:", reason);
  let deviceInfo = require("./deviceinfo").deviceInfo();
  require("./req").request(exports.getBackend() + "/api/unload", {
    ignoreLogin: true,
    method: "post",
    contentType: "application/x-www-form-urlencoded",
    content: {
      reason,
      deviceInfo: JSON.stringify(deviceInfo)
    }
  });
  // We can't rely on the server removing cookies, because the request may not
  // complete locally, since the addon is being destroyed
  removeCookies();
};

/** Remove the user and user.sig cookies for the backend */
function removeCookies() {
  let namespace = {};
  Cu.import('resource://gre/modules/Services.jsm', namespace);
  let domain = require("sdk/url").URL(exports.getBackend()).hostname;
  namespace.Services.cookies.add(domain, "/", "user", "", false, false, false, 0);
  namespace.Services.cookies.add(domain, "/", "user.sig", "", false, false, false, 0);
}
<|endoftext|>


<commit_before>function getMsgConsumers(scriptState) {
  var db = objDB.open(scriptState.ssID);
  var msgConsumers = [];

  var topSenders = {
    name: "Top Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      var rawFrom = msg.getFrom();
      var from = extractEmailAddress(rawFrom);
      var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
      if ( rows.length === 0) {
        objDB.insertRow(this.db, this.name, {From:from, Count:1} );
      } else {
        var newCount = rows[0].Count + 1;
        objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setDimensions(1024, 768)
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topMailingLists = {
    name: "Top Mailing Lists",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["MailingList", "Count"]);
    },
    msgFunction: function (msg) {
      var headers = extractHeaders(msg.getRawContent());
      if (headers.hasOwnProperty("list-id") && headers["list-id"].length === 1) {
        var listId = extractEmailAddress(headers["list-id"]);
        var rows = objDB.getRows(this.db, this.name, ['MailingList','Count'], {MailingList:listId});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {MailingList:listId, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {MailingList:listId, Count:newCount}, {MailingList:listId} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Mailing List"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topNonMailingListSenders = {
    name: "Top Non Mailing List Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      var headers = extractHeaders(msg.getRawContent());
      if (! headers.hasOwnProperty("list-id")) {
        var rawFrom = msg.getFrom();
        var from = extractEmailAddress(rawFrom);
        var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {From:from, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topRobotSenders = {
    name: "Top Robot Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      if (emailSentByRobot(msg.getRawContent())) {
        var rawFrom = msg.getFrom();
        var from = extractEmailAddress(rawFrom);
        var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {From:from, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topHumanSenders = {
    name: "Top Human Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      if (! emailSentByRobot(msg.getRawContent())) {
        var rawFrom = msg.getFrom();
        var from = extractEmailAddress(rawFrom);
        var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {From:from, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topApplicationErrors = {
    name: "Top Application Errors",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["Subject", "Count"]);
    },
    msgFunction: function (msg) {
      var fullSubject = msg.getSubject();
      // This is a crude attempt to group errors together, by only including
      // the first three words of the error.
      var errorRegex = /^\[Error [^\]]+\]\s\S+\s\S+\s\S+/;
      var match = fullSubject.match(errorRegex);
      if (match !== null) {
        var subject = match[0];
        var rows = objDB.getRows(this.db, this.name, ['Subject','Count'], {Subject:subject});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {Subject:subject, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {Subject:subject, Count:newCount}, {Subject:subject} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Application Error Partial Subject", textStyle: {fontSize: 10}})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '50%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  msgConsumers.push(topSenders);
  msgConsumers.push(topMailingLists);
  msgConsumers.push(topNonMailingListSenders);
  msgConsumers.push(topRobotSenders);
  msgConsumers.push(topHumanSenders);
  msgConsumers.push(topApplicationErrors);

  for(i = 0; i < msgConsumers.length; i += 1) {
    msgConsumers[i].db = db;
    msgConsumers[i].scriptState = scriptState;
  }

  return msgConsumers;
}
<commit_msg>Add Historical Email Volume Graph<commit_after>function getMsgConsumers(scriptState) {
  var db = objDB.open(scriptState.ssID);
  var msgConsumers = [];

  var topSenders = {
    name: "Top Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      var rawFrom = msg.getFrom();
      var from = extractEmailAddress(rawFrom);
      var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
      if ( rows.length === 0) {
        objDB.insertRow(this.db, this.name, {From:from, Count:1} );
      } else {
        var newCount = rows[0].Count + 1;
        objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setDimensions(1024, 768)
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topMailingLists = {
    name: "Top Mailing Lists",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["MailingList", "Count"]);
    },
    msgFunction: function (msg) {
      var headers = extractHeaders(msg.getRawContent());
      if (headers.hasOwnProperty("list-id") && headers["list-id"].length === 1) {
        var listId = extractEmailAddress(headers["list-id"]);
        var rows = objDB.getRows(this.db, this.name, ['MailingList','Count'], {MailingList:listId});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {MailingList:listId, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {MailingList:listId, Count:newCount}, {MailingList:listId} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Mailing List"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topNonMailingListSenders = {
    name: "Top Non Mailing List Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      var headers = extractHeaders(msg.getRawContent());
      if (! headers.hasOwnProperty("list-id")) {
        var rawFrom = msg.getFrom();
        var from = extractEmailAddress(rawFrom);
        var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {From:from, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topRobotSenders = {
    name: "Top Robot Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      if (emailSentByRobot(msg.getRawContent())) {
        var rawFrom = msg.getFrom();
        var from = extractEmailAddress(rawFrom);
        var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {From:from, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topHumanSenders = {
    name: "Top Human Senders",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["From", "Count"]);
    },
    msgFunction: function (msg) {
      if (! emailSentByRobot(msg.getRawContent())) {
        var rawFrom = msg.getFrom();
        var from = extractEmailAddress(rawFrom);
        var rows = objDB.getRows(this.db, this.name, ['From','Count'], {From:from});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {From:from, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {From:from, Count:newCount}, {From:from} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Sender"})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '40%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var topApplicationErrors = {
    name: "Top Application Errors",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["Subject", "Count"]);
    },
    msgFunction: function (msg) {
      var fullSubject = msg.getSubject();
      // This is a crude attempt to group errors together, by only including
      // the first three words of the error.
      var errorRegex = /^\[Error [^\]]+\]\s\S+\s\S+\s\S+/;
      var match = fullSubject.match(errorRegex);
      if (match !== null) {
        var subject = match[0];
        var rows = objDB.getRows(this.db, this.name, ['Subject','Count'], {Subject:subject});
        if ( rows.length === 0) {
          objDB.insertRow(this.db, this.name, {Subject:subject, Count:1} );
        } else {
          var newCount = rows[0].Count + 1;
          objDB.updateRow(this.db, this.name, {Subject:subject, Count:newCount}, {Subject:subject} );
        }
      }
    },
    graphFunction: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheetID = ss.getSheetByName(this.name).getSheetId();
      var encodedQuery = encodeURIComponent("select A,B order by B desc limit 10");
      var dataSourceURL = 'https://docs.google.com/spreadsheet/tq?key=' + this.scriptState.ssID;
      dataSourceURL += '&tq=' + encodedQuery;
      dataSourceURL += '&gid=' + sheetID;
      dataSourceURL += '&headers=-1';
      var chartBuilder = Charts.newBarChart()
      .setTitle(this.name)
      .setDimensions(1024, 768)
      .setOption('vAxis', {title: "Application Error Partial Subject", textStyle: {fontSize: 10}})
      .setOption('hAxis', {title: "Message Count", format: "decimal"})
      .setOption('chartArea', {left: '50%'})
      .setDataSourceUrl(dataSourceURL);
      this.chart = chartBuilder.build();
    },
  };

  var historicalEmailVolume = {
    name: "Historical Email Volume",
    db: null,
    scriptState: null,
    chart: null,
    initSpreadSheet: function () {
      var ss = SpreadsheetApp.openById(this.scriptState.ssID);
      var sheet = ss.insertSheet(this.name);
      sheet.appendRow(["MailingList", "Human"]);
    },
    msgFunction: function (msg) {
      var rows = objDB.getRows(this.db, this.name, ['MailingList','Human']);
      var headers = extractHeaders(msg.getRawContent());
      if (headers.hasOwnProperty("list-id") && headers["list-id"].length === 1) {
        if (rows.length === 0) {
          objDB.insertRow(this.db, this.name, {MailingList:1, Human:0} );
        } else {
          objDB.updateRow(this.db, this.name, {MailingList:(rows[0].MailingList + 1), Human:rows[0].Human});
        }
      } else {
        if (rows.length === 0) {
          objDB.insertRow(this.db, this.name, {MailingList:0, Human:1} );
        } else {
          objDB.updateRow(this.db, this.name, {MailingList:rows[0].MailingList, Human:(rows[0].Human + 1)});
        }
      }
    },
    graphFunction: function () {
      var historicalData = Charts.newDataTable()
        .addColumn(Charts.ColumnType.STRING, "Month")
        .addColumn(Charts.ColumnType.NUMBER, "MailingList")
        .addColumn(Charts.ColumnType.NUMBER, "Human");
      var rows;
      var file;
      var monthDatabase;
      var months = 0;
      var month = scriptState.monthToProcess.clone();
      var files = DriveApp.getFilesByName("Email3 Data - " + month.format('MMM YYYY'));
      while (months < 11 && files.hasNext()) {
        file = files.next();
        if (file.isTrashed()) {
          continue;
        }
        Logger.log(file.getName());
        monthDatabase = objDB.open(file.getId());
        rows = objDB.getRows(monthDatabase, this.name, ['MailingList','Human']);
        if (rows.length === 1) {
          Logger.log("MailingList: " + rows[0].MailingList + " Human: " + rows[0].Human);
          historicalData.addRow([month.format('MMM YYYY'), rows[0].MailingList, rows[0].Human]);
        }
        months += 1;
        month = month.subtract(1, 'days').startOf('month');
        files = DriveApp.getFilesByName("Email3 Data - " + month.format('MMM YYYY'));
      }

      var chartBuilder = Charts.newAreaChart()
        .setTitle(this.name)
        .setXAxisTitle('Month')
        .setYAxisTitle('Message Count')
        .setDimensions(1024, 768)
        .setStacked()
        .setPointStyle(Charts.PointStyle.MEDIUM)
        .setDataTable(historicalData);
      this.chart = chartBuilder.build();
    },
  };

  msgConsumers.push(historicalEmailVolume);
  msgConsumers.push(topSenders);
  msgConsumers.push(topMailingLists);
  msgConsumers.push(topNonMailingListSenders);
  msgConsumers.push(topRobotSenders);
  msgConsumers.push(topHumanSenders);
  msgConsumers.push(topApplicationErrors);

  for(i = 0; i < msgConsumers.length; i += 1) {
    msgConsumers[i].db = db;
    msgConsumers[i].scriptState = scriptState;
  }

  return msgConsumers;
}
<|endoftext|>


<commit_before>import InstanceListItem from './instanceListItem'
import Radium from 'radium'
import React from 'react'
import { mediaQueries } from '../../../styles/global'

const InstanceList = ({ process, showInstance }) => (

    {process.instances.map(instance =>
      <InstanceListItem
        instance={instance}
        key={instance.id}
        showInstance={showInstance}
      />
    )}

)

InstanceList.propTypes = {
  process: React.PropTypes.object.isRequired,
  showInstance: React.PropTypes.func.isRequired
}

export default Radium(InstanceList)

// Styling

const { small, medium, big } = mediaQueries(700, 990)
const style = {
  border: '1px solid #e5e5e5',
  borderRadius: '0 0 3px 3px',
  borderTop: '0',
  height: 'auto',
  overflowY: 'auto',
  padding: 0,
  [small]: {
    height: 500 - 20 - 40
  },
  [medium]: {
    height: 300 - 20 - 40
  },
  [big]: {
    height: 300 - 20 - 40
  }
}
<commit_msg>Change import eror<commit_after>import InstanceListItem from './InstanceListItem'
import Radium from 'radium'
import React from 'react'
import { mediaQueries } from '../../../styles/global'

const InstanceList = ({ process, showInstance }) => (

    {process.instances.map(instance =>
      <InstanceListItem
        instance={instance}
        key={instance.id}
        showInstance={showInstance}
      />
    )}

)

InstanceList.propTypes = {
  process: React.PropTypes.object.isRequired,
  showInstance: React.PropTypes.func.isRequired
}

export default Radium(InstanceList)

// Styling

const { small, medium, big } = mediaQueries(700, 990)
const style = {
  border: '1px solid #e5e5e5',
  borderRadius: '0 0 3px 3px',
  borderTop: '0',
  height: 'auto',
  overflowY: 'auto',
  padding: 0,
  [small]: {
    height: 500 - 20 - 40
  },
  [medium]: {
    height: 300 - 20 - 40
  },
  [big]: {
    height: 300 - 20 - 40
  }
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default {
  render: function(attribute, options) {
    var msg;

    for(var option in options) {
      msg = this.defaults[attribute].replace('{{' + option + '}}', options[option]);
    }

    return msg;
  },
  defaults: {
    include: "is not included in the list",
    exclude: "is reserved",
    required: "can't be blank",
    notrequired: "must be blank",
    maximum: "is too long (maximum is {{count}} characters)",
    minimum: "is too short (minimum is {{count}} characters)",
    is: "is the wrong length (should be {{count}} characters)",
    invalid: "is invalid",
    equals: "must be accepted",
    empty: "can't be empty",
    numeric: "is not a number",
    integer: "must be an integer",
    greaterThan: "must be greater than {{count}}",
    greaterThanOrEqualTo: "must be greater than or equal to {{count}}",
    equalTo: "must be equal to {{count}}",
    lessThan: "must be less than {{count}}",
    lessThanOrEqualTo: "must be less than or equal to {{count}}",
    odd: "must be odd",
    even: "must be even"
  }
};
<commit_msg>messages updated for new validator<commit_after>import Ember from 'ember';

export default {
  render: function(attribute, options) {
    var msg;

    for(var option in options) {
      msg = this.defaults[attribute].replace('{{' + option + '}}', options[option]);
    }

    return msg;
  },
  defaults: {
    include: "is not included in the list",
    exclude: "is reserved",
    required: "can't be blank",
    notrequired: "must be blank",
    maximum: "is too long (maximum is {{count}} characters)",
    minimum: "is too short (minimum is {{count}} characters)",
    is: "is the wrong length (should be {{count}} characters)",
    invalid: "is invalid",
    equals: "must be accepted",
    empty: "can't be empty",
    numeric: "is not a number",
    integer: "must be an integer",
    greaterThan: "must be greater than {{count}}",
    greaterThanOrEqualTo: "must be greater than or equal to {{count}}",
    equalTo: "must be equal to {{count}}",
    lessThan: "must be less than {{count}}",
    lessThanOrEqualTo: "must be less than or equal to {{count}}",
    odd: "must be odd",
    even: "must be even",
    phone: "valid phone number",
    ssn: "valid ssn",
    zip: "valid zip"
  }
};
<|endoftext|>


<commit_before>export default {
  presenceMessage: 'can\`t be blank',
  absenceMessage: 'must be blank',
  inclusionMessage: 'is not included in the list',
  exclusionMessage: 'is reserved',
  numericalityMessage: 'is not a number',
  mailMessage: 'is not a valid email',
  formatMessage: 'is invalid',
  colorMessage: 'must be a valid CSS hex color code',
  subdomainMessage: 'must be a valid subdomain',
  acceptanceMessage: 'must be accepted',
  zipCodeMessage: 'is not a valid zip code',
  URLMessage: 'must be a valid url',
  wrongLengthMessage: "is the wrong length (should be %@ characters)",
  tooShortMessage: "is too short (minimum is %@ characters)",
  tooLongMessage: "is too long (maximum is %@ characters)"
};<commit_msg>Added messages<commit_after>export default {
  presenceMessage: "can't be blank",
  absenceMessage: 'must be blank',
  inclusionMessage: 'is not included in the list',
  exclusionMessage: 'is reserved',
  numericalityMessage: 'is not a number',
  mailMessage: 'is not a valid email',
  formatMessage: 'is invalid',
  colorMessage: 'must be a valid CSS hex color code',
  subdomainMessage: 'must be a valid subdomain',
  acceptanceMessage: 'must be accepted',
  zipCodeMessage: 'is not a valid zip code',
  URLMessage: 'must be a valid url',
  wrongLengthMessage: "is the wrong length (should be %@ characters)",
  tooShortMessage: "is too short (minimum is %@ characters)",
  tooLongMessage: "is too long (maximum is %@ characters)"
  minLengthMessage: 'is too short. Minimum length is %@ characters',
  mustContainNumberMessage: 'must include a number',
  mustContainSpecialMessage: 'must include one of these special characters: %@',
  mustContainLowerMessage: 'must include a lower case character',
  mustContainCapitalMessage: 'must include an upper case character'
};
<|endoftext|>