<commit_before>'use strict';
// p0f v3 client - http://lcamtuf.coredump.cx/p0f3/

var net    = require('net');
var ipaddr = require('ipaddr.js');

function P0FClient(path) {
    var self = this;

    this.sock = null;
    this.send_queue = [];
    this.receive_queue = [];
    this.connected = false;
    this.ready = false;
    this.socket_has_error = false;
    this.restart_interval = false;

    var connect = function () {
        self.sock = net.createConnection(path);
        self.sock.setTimeout(5 * 1000);

        self.sock.on('connect', function () {
            self.sock.setTimeout(30 * 1000);
            self.connected = true;
            self.socket_has_error = false;
            self.ready = true;
            if (self.restart_interval) clearInterval(self.restart_interval);
            self.process_send_queue();
        });

        self.sock.on('data', function (data) {
            for (var i=0; i<data.length/232; i++) {
                self.decode_response(data.slice(((i) ? 232*i : 0), 232*(i+1)));
            }
        });

        self.sock.on('drain', function () {
            self.ready = true;
            self.process_send_queue();
        });

        self.sock.on('error', function (error) {
            self.connected = false;
            error.message = error.message + ' (socket: ' + path + ')';
            self.socket_has_error = error;
            self.sock.destroy();
            // Try and reconnect
            if (!self.restart_interval) {
                self.restart_interval = setInterval(function () {
                    connect();
                }, 5 * 1000);
            }
            // Clear the receive queue
            for (var i=0; i<self.receive_queue.length; i++) {
                var item = self.receive_queue.shift();
                item.cb(self.socket_has_error);
                continue;
            }
            self.process_send_queue();
        });
    };
    connect();
}

P0FClient.prototype.shutdown = function () {
    if (self.restart_interval) {
        clearInterval(self.restart_interval);
    }
}

P0FClient.prototype.decode_response = function (data) {
    var decode_string = function (data2, start, end) {
        var str = '';
        for (var a=start; a<end; a++) {
            var b = data2.readUInt8(a);
            if (b === 0x0) break;
            str = str + String.fromCharCode(b);
        }
        return str;
    };

    if (this.receive_queue.length <= 0) {
        throw new Error('unexpected data received');
    }
    var item = this.receive_queue.shift();

    ///////////////////
    // Decode packet //
    ///////////////////

    // Response magic dword (0x50304602), native endian.
    if (data.readUInt32LE(0) !== 0x50304602) {
        return item.cb(new Error('bad response magic!'));
    }
    // Status dword: 0x00 for 'bad query', 0x10 for 'OK', and 0x20 for 'no match'
    var st = data.readUInt32LE(4);
    switch (st) {
        case (0x00):
            return item.cb(new Error('bad query'));
        case (0x10):
            var p0f = {
                query:       item.ip,
                first_seen:  data.readUInt32LE(8),
                last_seen:   data.readUInt32LE(12),
                total_conn:  data.readUInt32LE(16),
                uptime_min:  data.readUInt32LE(20),
                up_mod_days: data.readUInt32LE(24),
                last_nat:    data.readUInt32LE(28),
                last_chg:    data.readUInt32LE(32),
                distance:    data.readInt16LE(36),
                bad_sw:      data.readUInt8(38),
                os_match_q:  data.readUInt8(39),
                os_name:     decode_string(data, 40, 72),
                os_flavor:   decode_string(data, 72, 104),
                http_name:   decode_string(data, 104, 136),
                http_flavor: decode_string(data, 136, 168),
                link_type:   decode_string(data, 168, 200),
                language:    decode_string(data, 200, 232),
            };
            return item.cb(null, p0f);
        case (0x20):
            return item.cb(null, null);
        default:
            throw new Error('unknown status: ' + st);
    }
};

P0FClient.prototype.query = function (ip, cb) {
    if (this.socket_has_error) {
        return cb(this.socket_has_error);
    }
    if (!this.connected) {
        return cb(new Error('socket not connected'));
    }
    var addr = ipaddr.parse(ip);
    var bytes = addr.toByteArray();
    var buf = new Buffer(21);
    buf.writeUInt32LE(0x50304601, 0); // query magic
    buf.writeUInt8(((addr.kind() === 'ipv6') ? 0x6 : 0x4), 4);
    for (var i=0; i < bytes.length; i++) {
        buf.writeUInt8(bytes[i], 5 + i);
    }
    if (!this.ready) {
        this.send_queue.push({ip: ip, cb: cb, buf: buf});
    }
    else {
        this.receive_queue.push({ip: ip, cb: cb});
        if (!this.sock.write(buf)) this.ready = false;
    }
};

P0FClient.prototype.process_send_queue = function () {
    if (this.send_queue.length === 0) { return; }

    for (var i=0; i<this.send_queue.length; i++) {
        var item;
        if (this.socket_has_error) {
            item = this.send_queue.shift();
            item.cb(this.socket_has_error);
            continue;
        }
        if (!this.ready) break;
        item = this.send_queue.shift();
        this.receive_queue.push({ip: item.ip, cb: item.cb});
        if (!this.sock.write(item.buf)) {
            this.ready = false;
        }
    }
};

exports.P0FClient = P0FClient;

exports.register = function () {
    this.cfg = this.config.get('connect.p0f.ini');
};

exports.hook_init_master = function (next, server) {
    var c = this.cfg.main;
    if (!c.socket_path) return next();
    // Start p0f process?
    server.notes.p0f_client = new P0FClient(c.socket_path);
    return next();
};

exports.hook_init_child = function (next, server) {
    var c = this.cfg.main;
    if (!c.socket_path) return next();
    server.notes.p0f_client = new P0FClient(c.socket_path);
    return next();
};

exports.hook_lookup_rdns = function onLookup(next, connection) {
    var plugin = this;
    if (!server.notes.p0f_client) {
        connection.logerror(plugin, 'missing server');
        return next();
    }
    var p0f_client = server.notes.p0f_client;
    p0f_client.query(connection.remote.ip, function (err, result) {
        if (err) {
            connection.results.add(plugin, {err: err.message});
            return next();
        }

        if (!result) {
            connection.results.add(plugin, {err: 'no p0f results'});
            return next();
        }

        connection.loginfo(plugin, format_results(result));
        connection.results.add(plugin, result);
        return next();
    });
};

function format_results(r) {
    var data = [];
    if (r.os_name) data.push('os="' + r.os_name + ' ' + r.os_flavor + '"');
    if (r.link_type) data.push('link_type="' + r.link_type + '"');
    if (r.distance) data.push('distance=' + r.distance);
    if (r.total_conn) data.push('total_conn=' + r.total_conn);
    if (r.last_nat) data.push('shared_ip=' + ((r.last_nat === 0) ? 'N' : 'Y'));
    return data.join(' ');
}

exports.hook_data_post = function (next, connection) {
    var plugin = this;
    var header_name = plugin.cfg.main.add_header;
    if (!header_name) {
        connection.logdebug(plugin, 'header disabled in ini' );
        return next();
    }

    connection.transaction.remove_header(header_name);
    var result = connection.results.get('connect.p0f');
    if (!result || !result.os_name) {
        connection.results.add(plugin, {err: 'no p0f note'});
        return next();
    }

    connection.logdebug(plugin, 'adding header');
    connection.transaction.add_header(header_name, format_results(result));

    return next();
};
<commit_msg>skip p0f on private IPs (#1758)<commit_after>'use strict';
// p0f v3 client - http://lcamtuf.coredump.cx/p0f3/

var net    = require('net');
var ipaddr = require('ipaddr.js');

function P0FClient(path) {
    var self = this;

    this.sock = null;
    this.send_queue = [];
    this.receive_queue = [];
    this.connected = false;
    this.ready = false;
    this.socket_has_error = false;
    this.restart_interval = false;

    var connect = function () {
        self.sock = net.createConnection(path);
        self.sock.setTimeout(5 * 1000);

        self.sock.on('connect', function () {
            self.sock.setTimeout(30 * 1000);
            self.connected = true;
            self.socket_has_error = false;
            self.ready = true;
            if (self.restart_interval) clearInterval(self.restart_interval);
            self.process_send_queue();
        });

        self.sock.on('data', function (data) {
            for (var i=0; i<data.length/232; i++) {
                self.decode_response(data.slice(((i) ? 232*i : 0), 232*(i+1)));
            }
        });

        self.sock.on('drain', function () {
            self.ready = true;
            self.process_send_queue();
        });

        self.sock.on('error', function (error) {
            self.connected = false;
            error.message = error.message + ' (socket: ' + path + ')';
            self.socket_has_error = error;
            self.sock.destroy();
            // Try and reconnect
            if (!self.restart_interval) {
                self.restart_interval = setInterval(function () {
                    connect();
                }, 5 * 1000);
            }
            // Clear the receive queue
            for (var i=0; i<self.receive_queue.length; i++) {
                var item = self.receive_queue.shift();
                item.cb(self.socket_has_error);
                continue;
            }
            self.process_send_queue();
        });
    };
    connect();
}

P0FClient.prototype.shutdown = function () {
    if (self.restart_interval) {
        clearInterval(self.restart_interval);
    }
}

P0FClient.prototype.decode_response = function (data) {
    var decode_string = function (data2, start, end) {
        var str = '';
        for (var a=start; a<end; a++) {
            var b = data2.readUInt8(a);
            if (b === 0x0) break;
            str = str + String.fromCharCode(b);
        }
        return str;
    };

    if (this.receive_queue.length <= 0) {
        throw new Error('unexpected data received');
    }
    var item = this.receive_queue.shift();

    ///////////////////
    // Decode packet //
    ///////////////////

    // Response magic dword (0x50304602), native endian.
    if (data.readUInt32LE(0) !== 0x50304602) {
        return item.cb(new Error('bad response magic!'));
    }
    // Status dword: 0x00 for 'bad query', 0x10 for 'OK', and 0x20 for 'no match'
    var st = data.readUInt32LE(4);
    switch (st) {
        case (0x00):
            return item.cb(new Error('bad query'));
        case (0x10):
            var p0f = {
                query:       item.ip,
                first_seen:  data.readUInt32LE(8),
                last_seen:   data.readUInt32LE(12),
                total_conn:  data.readUInt32LE(16),
                uptime_min:  data.readUInt32LE(20),
                up_mod_days: data.readUInt32LE(24),
                last_nat:    data.readUInt32LE(28),
                last_chg:    data.readUInt32LE(32),
                distance:    data.readInt16LE(36),
                bad_sw:      data.readUInt8(38),
                os_match_q:  data.readUInt8(39),
                os_name:     decode_string(data, 40, 72),
                os_flavor:   decode_string(data, 72, 104),
                http_name:   decode_string(data, 104, 136),
                http_flavor: decode_string(data, 136, 168),
                link_type:   decode_string(data, 168, 200),
                language:    decode_string(data, 200, 232),
            };
            return item.cb(null, p0f);
        case (0x20):
            return item.cb(null, null);
        default:
            throw new Error('unknown status: ' + st);
    }
};

P0FClient.prototype.query = function (ip, cb) {
    if (this.socket_has_error) {
        return cb(this.socket_has_error);
    }
    if (!this.connected) {
        return cb(new Error('socket not connected'));
    }
    var addr = ipaddr.parse(ip);
    var bytes = addr.toByteArray();
    var buf = new Buffer(21);
    buf.writeUInt32LE(0x50304601, 0); // query magic
    buf.writeUInt8(((addr.kind() === 'ipv6') ? 0x6 : 0x4), 4);
    for (var i=0; i < bytes.length; i++) {
        buf.writeUInt8(bytes[i], 5 + i);
    }
    if (!this.ready) {
        this.send_queue.push({ip: ip, cb: cb, buf: buf});
    }
    else {
        this.receive_queue.push({ip: ip, cb: cb});
        if (!this.sock.write(buf)) this.ready = false;
    }
};

P0FClient.prototype.process_send_queue = function () {
    if (this.send_queue.length === 0) { return; }

    for (var i=0; i<this.send_queue.length; i++) {
        var item;
        if (this.socket_has_error) {
            item = this.send_queue.shift();
            item.cb(this.socket_has_error);
            continue;
        }
        if (!this.ready) break;
        item = this.send_queue.shift();
        this.receive_queue.push({ip: item.ip, cb: item.cb});
        if (!this.sock.write(item.buf)) {
            this.ready = false;
        }
    }
};

exports.P0FClient = P0FClient;

exports.register = function () {
    this.cfg = this.config.get('connect.p0f.ini');
};

exports.hook_init_master = function (next, server) {
    var c = this.cfg.main;
    if (!c.socket_path) return next();
    // Start p0f process?
    server.notes.p0f_client = new P0FClient(c.socket_path);
    return next();
};

exports.hook_init_child = function (next, server) {
    var c = this.cfg.main;
    if (!c.socket_path) return next();
    server.notes.p0f_client = new P0FClient(c.socket_path);
    return next();
};

exports.hook_lookup_rdns = function onLookup(next, connection) {
    var plugin = this;
    if (connection.remote.is_private) return next();

    if (!server.notes.p0f_client) {
        connection.logerror(plugin, 'missing server');
        return next();
    }

    var p0f_client = server.notes.p0f_client;
    p0f_client.query(connection.remote.ip, function (err, result) {
        if (err) {
            connection.results.add(plugin, {err: err.message});
            return next();
        }

        if (!result) {
            connection.results.add(plugin, {err: 'no p0f results'});
            return next();
        }

        connection.loginfo(plugin, format_results(result));
        connection.results.add(plugin, result);
        return next();
    });
};

function format_results(r) {
    var data = [];
    if (r.os_name) data.push('os="' + r.os_name + ' ' + r.os_flavor + '"');
    if (r.link_type) data.push('link_type="' + r.link_type + '"');
    if (r.distance) data.push('distance=' + r.distance);
    if (r.total_conn) data.push('total_conn=' + r.total_conn);
    if (r.last_nat) data.push('shared_ip=' + ((r.last_nat === 0) ? 'N' : 'Y'));
    return data.join(' ');
}

exports.hook_data_post = function (next, connection) {
    var plugin = this;
    if (connection.remote.is_private) return next();

    var header_name = plugin.cfg.main.add_header;
    if (!header_name) {
        connection.logdebug(plugin, 'header disabled in ini' );
        return next();
    }

    connection.transaction.remove_header(header_name);
    var result = connection.results.get('connect.p0f');
    if (!result || !result.os_name) {
        connection.results.add(plugin, {err: 'no p0f note'});
        return next();
    }

    connection.logdebug(plugin, 'adding header');
    connection.transaction.add_header(header_name, format_results(result));

    return next();
};
<|endoftext|>


<commit_before>Template.postItem.onRendered(function () {
  // Get reference to template instance
  const instance = this;

  // Get Post ID from template instance
  const postId = instance.data.post._id;

  // Get reference to post DOM element
  const postElement = instance.$(`#${postId}`);

  // Render OEmbed content
  postElement.oembed();
});
<commit_msg>Added checking if logged user is post owner<commit_after>Template.postItem.onRendered(function () {
  // Get reference to template instance
  const instance = this;

  // Get Post ID from template instance
  const postId = instance.data.post._id;

  // Get reference to post DOM element
  const postElement = instance.$(`#${postId}`);

  // Render OEmbed content
  postElement.oembed();
});

Template.postItem.helpers({
  userIsPostOwner: function () {
    const instance = Template.instance();

    // Get Post ID from template instance
    const postOwnerId = instance.data.post.userId;
    const loggedUser = Meteor.userId();
    console.log("owner=" , loggedUser);
    return postOwnerId === loggedUser;
  }
})
<|endoftext|>


<commit_before>import Utils from '../utils'

function encode (string) {
  return encodeURIComponent(string)
}

function decode (string) {
  return decodeURIComponent(string)
}

function stringifyCookieValue (value) {
  return encode(value === Object(value) ? JSON.stringify(value) : '' + value)
}

function read (string) {
  if (string === '') {
    return string
  }

  if (string.indexOf('"') === 0) {
    // This is a quoted cookie as according to RFC2068, unescape...
    string = string.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\')
  }

  // Replace server-side written pluses with spaces.
  // If we can't decode the cookie, ignore it, it's unusable.
  // If we can't parse the cookie, ignore it, it's unusable.
  string = decode(string.replace(/\+/g, ' '))

  try {
    string = JSON.parse(string)
  }
  catch (e) {}

  return string
}

function set (key, value, options = {}) {
  let
    days = options.expires,
    time

  if (typeof options.expires === 'number') {
    time = new Date()
    time.setMilliseconds(time.getMilliseconds() + days * 864e+5)
  }

  document.cookie = [
    encode(key), '=', stringifyCookieValue(value),
    time ? '; expires=' + time.toUTCString() : '', // use expires attribute, max-age is not supported by IE
    options.path ? '; path=' + options.path : '',
    options.domain ? '; domain=' + options.domain : '',
    options.secure ? '; secure' : ''
  ].join('')
}

function get (key) {
  let
    result = key ? undefined : {},
    cookies = document.cookie ? document.cookie.split('; ') : [],
    i = 0,
    l = cookies.length,
    parts,
    name,
    cookie

  for (; i < l; i++) {
    parts = cookies[i].split('=')
    name = decode(parts.shift())
    cookie = parts.join('=')

    if (!key) {
      result[name] = cookie
    }
    else if (key === name) {
      result = read(cookie)
      break
    }
  }

  return result
}

function remove (key, options) {
  set(key, '', Utils.extend(true, {}, options, {
    expires: -1
  }))
}

function has (key) {
  return get(key) !== undefined
}

export default {
  get,
  set,
  has,
  remove,
  all: () => get()
}
<commit_msg>fix: Cookies.set ignores Date object in "expires" option #489<commit_after>import Utils from '../utils'

function encode (string) {
  return encodeURIComponent(string)
}

function decode (string) {
  return decodeURIComponent(string)
}

function stringifyCookieValue (value) {
  return encode(value === Object(value) ? JSON.stringify(value) : '' + value)
}

function read (string) {
  if (string === '') {
    return string
  }

  if (string.indexOf('"') === 0) {
    // This is a quoted cookie as according to RFC2068, unescape...
    string = string.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\')
  }

  // Replace server-side written pluses with spaces.
  // If we can't decode the cookie, ignore it, it's unusable.
  // If we can't parse the cookie, ignore it, it's unusable.
  string = decode(string.replace(/\+/g, ' '))

  try {
    string = JSON.parse(string)
  }
  catch (e) {}

  return string
}

function set (key, val, opts = {}) {
  let time = opts.expires

  if (typeof opts.expires === 'number') {
    time = new Date()
    time.setMilliseconds(time.getMilliseconds() + opts.expires * 864e+5)
  }

  document.cookie = [
    encode(key), '=', stringifyCookieValue(val),
    time ? '; expires=' + time.toUTCString() : '', // use expires attribute, max-age is not supported by IE
    opts.path ? '; path=' + opts.path : '',
    opts.domain ? '; domain=' + opts.domain : '',
    opts.secure ? '; secure' : ''
  ].join('')
}

function get (key) {
  let
    result = key ? undefined : {},
    cookies = document.cookie ? document.cookie.split('; ') : [],
    i = 0,
    l = cookies.length,
    parts,
    name,
    cookie

  for (; i < l; i++) {
    parts = cookies[i].split('=')
    name = decode(parts.shift())
    cookie = parts.join('=')

    if (!key) {
      result[name] = cookie
    }
    else if (key === name) {
      result = read(cookie)
      break
    }
  }

  return result
}

function remove (key, options) {
  set(key, '', Utils.extend(true, {}, options, {
    expires: -1
  }))
}

function has (key) {
  return get(key) !== undefined
}

export default {
  get,
  set,
  has,
  remove,
  all: () => get()
}
<|endoftext|>


<commit_before>"use strict";
const mongoose = require('mongoose');
const hm = require('./history-model');
const async = require('async')

module.exports = function historyPlugin(schema, options) {
  const customCollectionName  = options && options.customCollectionName;
  const customDiffAlgo = options && options.customDiffAlgo;
  const diffOnly  = options && options.diffOnly;
  const metadata = options && options.metadata;

  // Clear all history collection from Schema
  schema.statics.historyModel = function() {
    return hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options);
  };

  // Clear all history documents from history collection
  schema.statics.clearHistory = function(callback) {
    const History = hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options);
    History.remove({}, function(err) {
      callback(err);
    });
  };

  // Save original data
  schema.post( 'init', function() {
    if (diffOnly){
      this._original = this.toObject();
    }
  });

  function setMetadata(original, d, historyDoc, callback){
    async.each(metadata, (m, cb) => {
      if (typeof(m.value) === 'function'){
        if (m.value.length === 3){
          /** async function */
          m.value(original, d, function(err, data){
            if (err) cb(err);
            historyDoc[m.key] = data;
            cb();
          })
        } else {
          historyDoc[m.key] = m.value(original, d);
          cb();
        }
      } else {
        historyDoc[ m.key] = d ? d[ m.value] : null;
        cb();
      }
    }, callback)
  }

  // Create an copy when insert or update, or a diff log
  schema.pre('save', function(next) {
    const historyDoc = {};

    if(diffOnly && !this.isNew) {
      var original = this._original;
      delete this._original;
      var d = this.toObject();
      var diff = {};
      diff['_id'] = d['_id'];
      for(var k in d){
        if(customDiffAlgo) {
          var customDiff = customDiffAlgo(k, d[k], original[k]);
          if(customDiff) {
            diff[k] = customDiff.diff;
          }
        } else {
          if(String(d[k]) != String(original[k])){
            diff[k] = d[k];
          }
        }
      }
      diff.__v = undefined;
      historyDoc['t'] = new Date();
      historyDoc['o'] = 'u';
      historyDoc['d'] = diff;
    } else {
      var d = this.toObject();
      d.__v = undefined;
      historyDoc['t'] = new Date();
      historyDoc['o'] = this.isNew ? 'i' : 'u';
      historyDoc['d'] = d;
    }

    if (metadata){
      setMetadata(original, d, historyDoc, (err) => {
        if (err) return next(err)
        let history = new hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options)(historyDoc);
        history.save(next);
      })
    } else {
      let history = new hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options)(historyDoc);
      history.save(next);
    }
  });

  // Listen on update
  schema.pre('update', function(next) {
    let d = this._update.$set;
    d.__v = undefined;

    let historyDoc = {};
    historyDoc['t'] = new Date();
    historyDoc['o'] = 'u';
    historyDoc['d'] = d;
    if (metadata){
      setMetadata(this.toObject, d, historyDoc, (err) => {
        let history = new hm.HistoryModel(hm.historyCollectionName(this.mongooseCollection.collectionName, customCollectionName), options)(historyDoc);
        history.save(next);
      })
    } else {
      let history = new hm.HistoryModel(hm.historyCollectionName(this.mongooseCollection.collectionName, customCollectionName), options)(historyDoc);
      history.save(next);
    }
  });

  // Create an copy when insert or update
  schema.pre('remove', function(next) {
    let d = this.toObject();
    d.__v = undefined;
    let historyDoc = {};
    historyDoc['t'] = new Date();
    historyDoc['o'] = 'r';
    historyDoc['d'] = d;
    if (metadata){
      setMetadata(this.toObject(), this.toObject(), historyDoc, (err) =>{
        let history = new hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options)(historyDoc);
        history.save(next);
      })
    } else {
      let history = new hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options)(historyDoc);
      history.save(next);
    }
  });
};
<commit_msg>refactor to simplify creating history documents and saving to history model<commit_after>"use strict";
const mongoose = require('mongoose');
const hm = require('./history-model');
const async = require('async')

module.exports = function historyPlugin(schema, options) {
  const customCollectionName  = options && options.customCollectionName;
  const customDiffAlgo = options && options.customDiffAlgo;
  const diffOnly  = options && options.diffOnly;
  const metadata = options && options.metadata;

  // Clear all history collection from Schema
  schema.statics.historyModel = function() {
    return hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options);
  };

  // Clear all history documents from history collection
  schema.statics.clearHistory = function(callback) {
    const History = hm.HistoryModel(hm.historyCollectionName(this.collection.name, customCollectionName), options);
    History.remove({}, function(err) {
      callback(err);
    });
  };

  // Save original data
  schema.post( 'init', function() {
    if (diffOnly){
      this._original = this.toObject();
    }
  });

  function setMetadata(original, d, historyDoc, callback){
    async.each(metadata, (m, cb) => {
      if (typeof(m.value) === 'function'){
        if (m.value.length === 3){
          /** async function */
          m.value(original, d, function(err, data){
            if (err) cb(err);
            historyDoc[m.key] = data;
            cb();
          })
        } else {
          historyDoc[m.key] = m.value(original, d);
          cb();
        }
      } else {
        historyDoc[ m.key] = d ? d[ m.value] : null;
        cb();
      }
    }, callback)
  }

  // Create a copy when insert or update, or a diff log
  schema.pre('save', function(next) {
    let historyDoc = {};

    if(diffOnly && !this.isNew) {
      var original = this._original;
      delete this._original;
      var d = this.toObject();
      var diff = {};
      diff['_id'] = d['_id'];
      for(var k in d){
        if(customDiffAlgo) {
          var customDiff = customDiffAlgo(k, d[k], original[k]);
          if(customDiff) {
            diff[k] = customDiff.diff;
          }
        } else {
          if(String(d[k]) != String(original[k])){
            diff[k] = d[k];
          }
        }
      }

      historyDoc = createHistoryDoc(diff, 'u');
    } else {
      var d = this.toObject();
      let operation = this.isNew ? 'i' : 'u';
      historyDoc = createHistoryDoc(d, operation);
    }

    saveHistoryModel(original, d, historyDoc, this.collection.name, next);
  });

  // Listen on update
  schema.pre('update', function(next) {
    let d = this._update.$set;
    let historyDoc = createHistoryDoc(d, 'u');

    saveHistoryModel(this.toObject, d, historyDoc, this.mongooseCollection.collectionName, next);
  });

  // Create a copy on remove
  schema.pre('remove', function(next) {
    let d = this.toObject();
    let historyDoc = createHistoryDoc(d, 'r');

    saveHistoryModel(this.toObject(), d, historyDoc, this.collection.name, next);
  });

  function createHistoryDoc(d, operation) {
    d.__v = undefined;

    let historyDoc = {};
    historyDoc['t'] = new Date();
    historyDoc['o'] = operation;
    historyDoc['d'] = d;

    return historyDoc;
  }

  function saveHistoryModel(original, d, historyDoc, collectionName, next) {
    if (metadata) {
      setMetadata(original, d, historyDoc, (err) => {
        if (err) return next(err);
        let history = new hm.HistoryModel(hm.historyCollectionName(collectionName, customCollectionName), options)(historyDoc);
        history.save(next);
      });
    } else {
      let history = new hm.HistoryModel(hm.historyCollectionName(collectionName, customCollectionName), options)(historyDoc);
      history.save(next);
    }
  }

};
<|endoftext|>


<commit_before><commit_msg>Georesonator hinting for ai<commit_after><|endoftext|>


<commit_before>'use strict';
module.exports =
class IPInfo {
    constructor() {
        this.ipinfo = require('ipinfo');
    }

    sendPlainTextResponse(res, payload) {
        this.ipinfo(payload.text, function (err, info) {
            if (err) {
                res.status(500).send(err);
            } else {
                res.send(info);
            }
        });
    }

    sendPrettyResponse(res, payload) {
        let superagent = require('superagent'),
            self = this;
        const WEBHOOK = process.env.WEBHOOK;

        this.ipinfo(payload.text, function (err, info) {
            if (err) {
                res.status(500).send(err);
            } else {
                let message = {
                    username: 'IPInfo',
                    icon_url: 'http://vignette1.wikia.nocookie.net/cowboybebop/images/c/cd/6_Ein1.png/revision/latest?cb=20091209161501',
                    channel: payload.channel_id || '@slackbot',
                    attachments: [{
                        title: "IP Info for " + info.ip,
                        title_link: "http://ipinfo.io/" + info.ip,
                        fields: [
                            {
                                title: 'City',
                                value: info.city,
                                short: true
                            }, {
                                title: 'Region',
                                value: info.region,
                                short: true
                            }, {
                                title: 'Postal',
                                value: info.postal,
                                short: true
                            }, {
                                title: 'Country',
                                value: info.country,
                                short: true
                            }, {
                                title: 'Hostname',
                                value: info.hostname
                            }, {
                                title: 'Org',
                                value: info.org
                            }
                        ]
                    }]
                };

                console.log('posting message', message);

                superagent.post(WEBHOOK, message, function (err) {
                    if (err) {
                        console.log('Error posting to slack!', err.toString());
                        self.sendPlainTextResponse(res, payload);
                    } else {
                        res.status(200).end();
                    }
                });
            }
        });
    }
}
<commit_msg>only add fields available<commit_after>'use strict';
module.exports =
class IPInfo {
    constructor() {
        this.ipinfo = require('ipinfo');
    }

    sendPlainTextResponse(res, payload) {
        this.ipinfo(payload.text, function (err, info) {
            if (err) {
                res.status(500).send(err);
            } else {
                res.send(info);
            }
        });
    }

    sendPrettyResponse(res, payload) {
        let superagent = require('superagent'),
            self = this;
        const WEBHOOK = process.env.WEBHOOK;

        this.ipinfo(payload.text, function (err, info) {
            if (err) {
                res.status(500).send(err);
            } else {
                let fields = [],
                    message = {
                        username: 'IPInfo',
                        icon_url: 'http://vignette1.wikia.nocookie.net/cowboybebop/images/c/cd/6_Ein1.png/revision/latest?cb=20091209161501',
                        channel: payload.channel_id || '@slackbot',
                        attachments: [{
                            title: "IP Info for " + info.ip,
                            title_link: "http://ipinfo.io/" + info.ip,
                            fields: fields
                        }]
                    },
                    addField = function addField(title, value, short = true) {
                        if (value) {
                            fields.push({
                                title: title,
                                value: value,
                                short: short
                            });
                        }
                    };

                addField('City', info.city);
                addField('Region', info.region);
                addField('Postal', info.postal);
                addField('Country', info.country);
                addField('Hostname', info.hostname, false);
                addField('Organiziation', info.org, false);

                console.log('posting message', message);

                superagent.post(WEBHOOK, message, function (err) {
                    if (err) {
                        console.log('Error posting to slack!', err.toString());
                        self.sendPlainTextResponse(res, payload);
                    } else {
                        res.status(200).end();
                    }
                });
            }
        });
    }
}
<|endoftext|>


<commit_before>/* eslint-disable no-return-assign */
import '@polymer/iron-icon/iron-icon';
import '@polymer/paper-input/paper-input';
import './ui-helpers/cosmoz-clear-button';

import { applySingleFilter, columnMixin, getString } from './cosmoz-omnitable-column-mixin';
import { PolymerElement } from '@polymer/polymer/polymer-element';
import { html } from 'lit-html';

const
	onChange = setState => event => setState(state => {
		clearInterval(state.t);
		const t = setTimeout(() => setState(state => ({ ...state, filter: state.inputValue })), 1000);
		return { ...state, inputValue: event.target.value, t };
	}),

	onBlur = setState => () =>
		setState(state => ({ ...state, filter: state.inputValue })),

	onKeyDown = setState => event => {
		if (event.keyCode === 13) {
			event.preventDefault();
			setState(state => ({ ...state, filter: state.inputValue }));
		}
	},

	onFocus = setState => event =>
		setState(state => ({ ...state, headerFocused: event.detail.value })),

	resetFilter = setState => () =>
		setState(state => ({ ...state, filter: undefined, inputValue: undefined })),

	hasFilter = filter => filter != null && filter !== '';

/**
 * @polymer
 * @customElement
 * @appliesMixin columnMixin
 */
class OmnitableColumn extends columnMixin(PolymerElement) {
	static get properties() {
		return {
			minWidth: { type: String, value: '55px' },
			editMinWidth: { type: String, value: '55px' },
			inputValue: { type: Object, notify: true }
		};
	}

	getFilterFn(column, filter) {
		if (filter == null || filter === '') {
			return;
		}
		return applySingleFilter(column, filter);
	}

	renderCell(column, { item }) {
		return html`<span class="default-column">${ getString(column, item) }</span>`;
	}

	renderEditCell(column, { item }, onItemChange) {
		const onChange = event => onItemChange(event.target.value);
		return html`<paper-input no-label-float type="text" @change=${ onChange } .value=${ getString(column, item) }></paper-input>`;
	}

	renderHeader(column, { filter, inputValue, headerFocused }, setState) {
		return html`<paper-input
			label=${ column.title }
			.value=${ inputValue ?? filter }
			@value-changed=${ onChange(setState) }
			focused=${ headerFocused }
			@focused-changed=${ onFocus(setState) }
			@keydown=${ onKeyDown(setState) }
			@blur=${ onBlur(setState) }
		>
			<cosmoz-clear-button suffix slot="suffix" ?visible=${ hasFilter(filter) } light @click=${ resetFilter(setState) }></cosmoz-clear-button>
		</paper-input>`;
	}
}
customElements.define('cosmoz-omnitable-column', OmnitableColumn);
<commit_msg>fix: use null for filter reset<commit_after>/* eslint-disable no-return-assign */
import '@polymer/iron-icon/iron-icon';
import '@polymer/paper-input/paper-input';
import './ui-helpers/cosmoz-clear-button';

import { applySingleFilter, columnMixin, getString } from './cosmoz-omnitable-column-mixin';
import { PolymerElement } from '@polymer/polymer/polymer-element';
import { html } from 'lit-html';

const
	onChange = setState => event => setState(state => {
		clearInterval(state.t);
		const t = setTimeout(() => setState(state => ({ ...state, filter: state.inputValue })), 1000);
		return { ...state, inputValue: event.target.value, t };
	}),

	onBlur = setState => () =>
		setState(state => ({ ...state, filter: state.inputValue })),

	onKeyDown = setState => event => {
		if (event.keyCode === 13) {
			event.preventDefault();
			setState(state => ({ ...state, filter: state.inputValue }));
		}
	},

	onFocus = setState => event =>
		setState(state => ({ ...state, headerFocused: event.detail.value })),

	resetFilter = setState => () =>
		setState(state => ({ ...state, filter: null, inputValue: null })),

	hasFilter = filter => filter != null && filter !== '';

/**
 * @polymer
 * @customElement
 * @appliesMixin columnMixin
 */
class OmnitableColumn extends columnMixin(PolymerElement) {
	static get properties() {
		return {
			minWidth: { type: String, value: '55px' },
			editMinWidth: { type: String, value: '55px' },
			inputValue: { type: Object, notify: true }
		};
	}

	getFilterFn(column, filter) {
		if (filter == null || filter === '') {
			return;
		}
		return applySingleFilter(column, filter);
	}

	renderCell(column, { item }) {
		return html`<span class="default-column">${ getString(column, item) }</span>`;
	}

	renderEditCell(column, { item }, onItemChange) {
		const onChange = event => onItemChange(event.target.value);
		return html`<paper-input no-label-float type="text" @change=${ onChange } .value=${ getString(column, item) }></paper-input>`;
	}

	renderHeader(column, { filter, inputValue, headerFocused }, setState) {
		return html`<paper-input
			label=${ column.title }
			.value=${ inputValue ?? filter }
			@value-changed=${ onChange(setState) }
			focused=${ headerFocused }
			@focused-changed=${ onFocus(setState) }
			@keydown=${ onKeyDown(setState) }
			@blur=${ onBlur(setState) }
		>
			<cosmoz-clear-button suffix slot="suffix" ?visible=${ hasFilter(filter) } light @click=${ resetFilter(setState) }></cosmoz-clear-button>
		</paper-input>`;
	}
}
customElements.define('cosmoz-omnitable-column', OmnitableColumn);
<|endoftext|>


<commit_before>var sound = 0;
var USER_REGEX = /^[a-zA-Z-_0-9]{1,16}$/;
var HISTORY_STORAGE_NAME = 'history';
var MAX_STORAGE_LENGTH = 3000;

var $ = function(id) {
	return document.getElementById(id);
};

function onDocLoad(onload) {
	return document.addEventListener("DOMContentLoaded", onload);
}

onDocLoad(function () {
	mute();
	if (typeof InstallTrigger !== 'undefined') {
		console.warn(getDebugMessage("Ops, there's no scrollbar for firefox"));
	}
});

function mute() {
	if (sound < 3) {
		sound ++;
	} else {
		sound = 0
	}
	var btn = $("muteBtn");
	switch (sound) {
		case 0:
			btn.className = 'icon-volume-off';
			break;
		case 1:
			btn.className = 'icon-volume-1';
			break;
		case 2:
			btn.className = 'icon-volume-2';
			break;
		case 3:
			btn.className = 'icon-volume-3';
			break;
	}
}

function checkAndPlay(element) {
	if (!element.readyState) {
		element.load();
	}
	if (element.readyState && sound) {
		element.pause();
		element.currentTime = 0;
		if (element.currentTime === element.duration ){
			// TODO currentType is not set sometimes
			var params = {
				browser : getBrowserVersion(),
				issue : "html5 audio currentTime"
			};
			doPost('/report_issue', params, null, null);
			console.warn(getDebugMessage("Can't set current time for audio on browser {}. Reloading it"), getBrowserVersion());
		}
		switch (sound) {
			case 1:
				element.volume = 0.15;
				break;
			case 2:
				element.volume = 0.4;
				break;
			case 3:
				element.volume = 1;
		}
		element.play();
	}
}

function getBrowserVersion() {
	var ua = navigator.userAgent, tem,
		M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
	if (/trident/i.test(M[1])) {
		tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
		return 'IE ' + (tem[1] || '');
	}
	if (M[1] === 'Chrome') {
		tem = ua.match(/\bOPR\/(\d+)/);
		if (tem != null) return 'Opera ' + tem[1];
	}
	M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
	if ((tem = ua.match(/version\/(\d+)/i)) != null) M.splice(1, 1, tem[1]);
	return M.join(' ');
}

function readCookie(name, c, C, i) {
	c = document.cookie.split('; ');
	var cookies = {};
	for (i = c.length - 1; i >= 0; i--) {
		C = c[i].split('=');
		cookies[C[0]] = C[1];
	}
	var cookie = cookies[name];
	if (cookie != null) {
		var length = cookie.length - 1;
		// if cookie is wrapped with quotes (for ex api)
		if (cookie[0] == '"' && cookie[length] == '"') {
			cookie = cookie.substring(1, length);
		}
	}
	return cookie;
}

/**
 * @param params : map dict of params or DOM form
 * @param callback : function calls on response
 * @param url : string url to post
 * @param form : form in canse form is used
 * */
function doPost(url, params, callback, form) {
	var r = new XMLHttpRequest();
	r.onreadystatechange = function () {
		if (r.readyState == 4) {
			if (r.status == 200) {
				console.log(getDebugMessage("POST {} in: {};", url, r.response));
				if (typeof(callback) == "function") {
					callback(r.response);
				} else {
					console.warn(getDebugMessage("Skipping {} callback for POST {}", callback, url));
				}
			} else {
				console.error(getDebugMessage("POST {} in: {}, status:", url, r.response, r.status));
			}
		}
	};
	var data;
	if (form != null) {
		data = new FormData(form);
	} else {
		data = new FormData();
	}
	if (params) {
		for (var key in params) {
			if (params.hasOwnProperty(key)) {
				data.append(key, params[key]);
			}
		}
	}
	if (url == "") {
		url = window.location.href ; // f*cking IE
	}
	r.open("POST", url, true);
	r.setRequestHeader("X-CSRFToken", readCookie("csrftoken"));
	console.log(getDebugMessage("POST {} out: {}", url, params));
	r.send(data);
}

/**
 * Loads file from server on runtime */
function doGet(fileUrl, callback) {
	// TODO load doesn't work in IE for pikaday
	var fileTypeRegex = /\w+$/;
	var typeRegRes = fileTypeRegex.exec(fileUrl);
	if (typeRegRes != null) {
		var fileType = typeRegRes[0];
		var fileRef = null;
		switch (fileType) {
			case 'js':
				fileRef = document.createElement('script');
				fileRef.setAttribute("type", "text/javascript");
				fileRef.setAttribute("src", fileUrl);
				break;
			case 'css':
				fileRef = document.createElement("link");
				fileRef.setAttribute("rel", "stylesheet");
				fileRef.setAttribute("type", "text/css");
				fileRef.setAttribute("href", fileUrl);
				break;
			case 'json':
				var xobj = new XMLHttpRequest();
				// special for IE
				if (xobj.overrideMimeType) {
					xobj.overrideMimeType("application/json");
				}
				xobj.open('GET', fileUrl, true); // Replace 'my_data' with the path to your file
				xobj.onreadystatechange = function () {
					if (xobj.readyState == 4 && xobj.status == "200") {
						callback(xobj.responseText);
					}
				};
				xobj.send(null);
				break;
			default:
				console.error(getDebugMessage('Unknown type of style {}', fileType))
		}
		if (fileRef) {
			document.getElementsByTagName("head")[0].appendChild(fileRef);
			fileRef.onload = callback;
		}
	} else {
		console.error(getDebugMessage('File type regex failed for filename "{}"', fileUrl));
	}
}

function saveLogToStorage(result) {
	var storageInfo = localStorage.getItem(HISTORY_STORAGE_NAME);
	var newStorage;
	if (storageInfo == null) {
		newStorage = result;
	} else if (localStorage.length > MAX_STORAGE_LENGTH) {
		var notConcatInfo = storageInfo +';;;'+ result;
		newStorage = notConcatInfo.substr(notConcatInfo.length - MAX_STORAGE_LENGTH, notConcatInfo.length);
	} else {
		newStorage = storageInfo + ';;;' + result;
	}
	localStorage.setItem(HISTORY_STORAGE_NAME, newStorage);
}

function hideElement(element, className) {
	if (className == null) {
		className = 'hidden';
	}
	if (element.className == null) {
		element.className = '';
	}
	if (element.className.indexOf(className) < 0) {
		element.className += " " + className;
	}
}

function showElement(element, className) {
	if (className == null) {
		className = 'hidden';
	}
	if (element.className == null) {
		return;
	}
	element.className = element.className.replace(className, '');
}

function toogleVisibility(element) {
	if (element.className == null) {
		element.className = '';
	}
	if (element.className.indexOf('hidden') > -1) {
		showElement(element);
	} else {
		hideElement(element)
	}
}

/**
 *
 * Formats message for debug,
 * Usage getDebugMessage("{} is {}", 'war', 'bad');
 * @returns: "15:9:31:839: war is bad"
 *  */
function getDebugMessage() {
	var now = new Date();
	// first argument is format, others are params
	for (var i = 1; i < arguments.length; i++) {
		arguments[0] = arguments[0].replace('{}', arguments[i]);
	}
	var time = [now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds()].join(':');
	var result = time + ': ' + arguments[0];
	saveLogToStorage(result);
	return result;
}
<commit_msg>fixed possible npe on loading json from server<commit_after>var sound = 0;
var USER_REGEX = /^[a-zA-Z-_0-9]{1,16}$/;
var HISTORY_STORAGE_NAME = 'history';
var MAX_STORAGE_LENGTH = 3000;

var $ = function(id) {
	return document.getElementById(id);
};

function onDocLoad(onload) {
	return document.addEventListener("DOMContentLoaded", onload);
}

onDocLoad(function () {
	mute();
	if (typeof InstallTrigger !== 'undefined') {
		console.warn(getDebugMessage("Ops, there's no scrollbar for firefox"));
	}
});

function mute() {
	if (sound < 3) {
		sound ++;
	} else {
		sound = 0
	}
	var btn = $("muteBtn");
	switch (sound) {
		case 0:
			btn.className = 'icon-volume-off';
			break;
		case 1:
			btn.className = 'icon-volume-1';
			break;
		case 2:
			btn.className = 'icon-volume-2';
			break;
		case 3:
			btn.className = 'icon-volume-3';
			break;
	}
}

function checkAndPlay(element) {
	if (!element.readyState) {
		element.load();
	}
	if (element.readyState && sound) {
		element.pause();
		element.currentTime = 0;
		if (element.currentTime === element.duration ){
			// TODO currentType is not set sometimes
			var params = {
				browser : getBrowserVersion(),
				issue : "html5 audio currentTime"
			};
			doPost('/report_issue', params, null, null);
			console.warn(getDebugMessage("Can't set current time for audio on browser {}. Reloading it"), getBrowserVersion());
		}
		switch (sound) {
			case 1:
				element.volume = 0.15;
				break;
			case 2:
				element.volume = 0.4;
				break;
			case 3:
				element.volume = 1;
		}
		element.play();
	}
}

function getBrowserVersion() {
	var ua = navigator.userAgent, tem,
		M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
	if (/trident/i.test(M[1])) {
		tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
		return 'IE ' + (tem[1] || '');
	}
	if (M[1] === 'Chrome') {
		tem = ua.match(/\bOPR\/(\d+)/);
		if (tem != null) return 'Opera ' + tem[1];
	}
	M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
	if ((tem = ua.match(/version\/(\d+)/i)) != null) M.splice(1, 1, tem[1]);
	return M.join(' ');
}

function readCookie(name, c, C, i) {
	c = document.cookie.split('; ');
	var cookies = {};
	for (i = c.length - 1; i >= 0; i--) {
		C = c[i].split('=');
		cookies[C[0]] = C[1];
	}
	var cookie = cookies[name];
	if (cookie != null) {
		var length = cookie.length - 1;
		// if cookie is wrapped with quotes (for ex api)
		if (cookie[0] == '"' && cookie[length] == '"') {
			cookie = cookie.substring(1, length);
		}
	}
	return cookie;
}

/**
 * @param params : map dict of params or DOM form
 * @param callback : function calls on response
 * @param url : string url to post
 * @param form : form in canse form is used
 * */
function doPost(url, params, callback, form) {
	var r = new XMLHttpRequest();
	r.onreadystatechange = function () {
		if (r.readyState == 4) {
			if (r.status == 200) {
				console.log(getDebugMessage("POST {} in: {};", url, r.response));
				if (typeof(callback) == "function") {
					callback(r.response);
				} else {
					console.warn(getDebugMessage("Skipping {} callback for POST {}", callback, url));
				}
			} else {
				console.error(getDebugMessage("POST {} in: {}, status:", url, r.response, r.status));
			}
		}
	};
	var data;
	if (form != null) {
		data = new FormData(form);
	} else {
		data = new FormData();
	}
	if (params) {
		for (var key in params) {
			if (params.hasOwnProperty(key)) {
				data.append(key, params[key]);
			}
		}
	}
	if (url == "") {
		url = window.location.href ; // f*cking IE
	}
	r.open("POST", url, true);
	r.setRequestHeader("X-CSRFToken", readCookie("csrftoken"));
	console.log(getDebugMessage("POST {} out: {}", url, params));
	r.send(data);
}

/**
 * Loads file from server on runtime */
function doGet(fileUrl, callback) {
	// TODO load doesn't work in IE for pikaday
	var fileTypeRegex = /\w+$/;
	var typeRegRes = fileTypeRegex.exec(fileUrl);
	if (typeRegRes != null) {
		var fileType = typeRegRes[0];
		var fileRef = null;
		switch (fileType) {
			case 'js':
				fileRef = document.createElement('script');
				fileRef.setAttribute("type", "text/javascript");
				fileRef.setAttribute("src", fileUrl);
				break;
			case 'css':
				fileRef = document.createElement("link");
				fileRef.setAttribute("rel", "stylesheet");
				fileRef.setAttribute("type", "text/css");
				fileRef.setAttribute("href", fileUrl);
				break;
			case 'json':
				var xobj = new XMLHttpRequest();
				// special for IE
				if (xobj.overrideMimeType) {
					xobj.overrideMimeType("application/json");
				}
				xobj.open('GET', fileUrl, true); // Replace 'my_data' with the path to your file
				xobj.onreadystatechange = function () {
					if (xobj.readyState == 4 && xobj.status == "200") {
						if (callback) {
							callback(xobj.responseText);
						}
					}
				};
				xobj.send(null);
				break;
			default:
				console.error(getDebugMessage('Unknown type of style {}', fileType))
		}
		if (fileRef) {
			document.getElementsByTagName("head")[0].appendChild(fileRef);
			fileRef.onload = callback;
		}
	} else {
		console.error(getDebugMessage('File type regex failed for filename "{}"', fileUrl));
	}
}

function saveLogToStorage(result) {
	var storageInfo = localStorage.getItem(HISTORY_STORAGE_NAME);
	var newStorage;
	if (storageInfo == null) {
		newStorage = result;
	} else if (localStorage.length > MAX_STORAGE_LENGTH) {
		var notConcatInfo = storageInfo +';;;'+ result;
		newStorage = notConcatInfo.substr(notConcatInfo.length - MAX_STORAGE_LENGTH, notConcatInfo.length);
	} else {
		newStorage = storageInfo + ';;;' + result;
	}
	localStorage.setItem(HISTORY_STORAGE_NAME, newStorage);
}

function hideElement(element, className) {
	if (className == null) {
		className = 'hidden';
	}
	if (element.className == null) {
		element.className = '';
	}
	if (element.className.indexOf(className) < 0) {
		element.className += " " + className;
	}
}

function showElement(element, className) {
	if (className == null) {
		className = 'hidden';
	}
	if (element.className == null) {
		return;
	}
	element.className = element.className.replace(className, '');
}

function toogleVisibility(element) {
	if (element.className == null) {
		element.className = '';
	}
	if (element.className.indexOf('hidden') > -1) {
		showElement(element);
	} else {
		hideElement(element)
	}
}

/**
 *
 * Formats message for debug,
 * Usage getDebugMessage("{} is {}", 'war', 'bad');
 * @returns: "15:9:31:839: war is bad"
 *  */
function getDebugMessage() {
	var now = new Date();
	// first argument is format, others are params
	for (var i = 1; i < arguments.length; i++) {
		arguments[0] = arguments[0].replace('{}', arguments[i]);
	}
	var time = [now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds()].join(':');
	var result = time + ': ' + arguments[0];
	saveLogToStorage(result);
	return result;
}
<|endoftext|>


<commit_before>/* Table of contents:
 * 1. Upload section
 *   a. globals
 *   b. bang()
 *   c. start()
 *   d. uploadHate()
 *   e. localHateGet()
 *   f. transferComplete()
 *   g. transferFailed()
 *   h. transferCanceled()
 *   i. storeHate()
 *   j. restart()
 *   k. interpretStatus()
 *   l. uploadSuccess()
 * 2. Content Scripts Connection
 * 999. do stuff*/

/*
 *------------------------------------------------------------------------------
 * 1. Upload section.
 *------------------------------------------------------------------------------
 */

// a. globals
var ON_HAND = 1;
var KNOW_LOCAL = 2;
var IS_LOCAL = 4;
var UPLOAD = 8;
var ABORT = 16;
var RESTART = 32;
var hate = null;
var hatestatus = 0;

/* 1  - is it on hand
 * 2  - do we know if it is locally stored?
 * 4  - is it locally stored?
 * 8  - was upload successful?
 * 16 - was upload aborted?
 * 32 - have we tried restarting?*/

// b. bang()
function bang() {
  chrome.storage.local.get("hatestatus", start);
}

// c. start()
/* This should be what happens first when the addon starts.*/
function start(status) {
  if(chrome.runtime.lastError) { // if we had trouble getting the status.
    console.log(chrome.runtime.lastError);
    hatestatus = hatestatus | RESTART; // assume we restarted.
  } else if(status.hasOwnProperty("hatestatus")) { // if status is local.
    hatestatus = status.hatestatus; // get most up to date status.
  } else {
    chrome.storage.local.set({"hatestatus": hatestatus});
  }
  if(hatestatus & ON_HAND === ON_HAND) {
    if(hate == null) {
      hatestatus -= ON_HAND;
    } else {
      return;
    }
  }
  if(hatestatus & (KNOW_LOCAL + IS_LOCAL) === KNOW_LOCAL) {
    uploadHate();
  } else {
    chrome.storage.local.get("hatedata", localHateGet);
  }
}

// d. uploadHate()
/* This function takes the information from hbu.json and makes it accessible
 * to the addon.*/
function uploadHate() {
  var hateURL = chrome.extension.getURL("web_source/hbu.json");
  var xobj = new XMLHttpRequest();
  xobj.addEventListener("load", transferComplete);
  xobj.addEventListener("error", transferFailed);
  xobj.addEventListener("abort", transferCanceled);
  xobj.overrideMimeType("application/json");
  xobj.open('GET', hateURL);
  xobj.send();
}

// e. localHateGet()
/* This function should only be called after an attempt to retrieve hatedata
 * locally. If the retrieval is unsuccessful for any reason it tries to
 * upload the content from the addon data. If the retrieval is successful then
 * nothing more need be done.*/
function localHateGet(data) {
  if(chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError);
    uploadHate();
  } else {
    var local = null;
    try {
      local = data.hasOwnProperty("hatedata");
    } catch (e) {
      local = false;
    }
    if(local) {
      hate = data.hatedata;
      hatestatus = hatestatus | (ON_HAND + KNOW_LOCAL + IS_LOCAL);
      hatestatus = hatestatus & ~RESTART;
      chrome.storage.local.set({"hatestatus": hatestatus});
      uploadSuccess();
    } else {
      hatestatus = hatestatus | KNOW_LOCAL;
      hatestatus = hatestatus & ~IS_LOCAL;
      uploadHate();
    }
  }
}

// f. transferComplete()
/* This function is called if an upload from the addon data is successful.
 * If hatedata is not stored locally then it attempts to store it locally.*/
function transferComplete() {
  hate = JSON.parse(this.responseText);
  hatestatus = hatestatus | (ON_HAND + UPLOAD);
  hatestatus = hatestatus & ~(ABORT + RESTART);
  chrome.storage.local.set({"hatestatus": hatestatus});
  uploadSuccess();
  if((hatestatus & (KNOW_LOCAL + IS_LOCAL)) != (KNOW_LOCAL + IS_LOCAL)) {
    chrome.storage.local.set({"hatedata": hate}, storeHate);
  }
}

// g. transferFailed()
/* This function is called if an upload from the addon data fails. If a reload
 * has not been attempted yet, then the function attempts a reload. If a reload
 * has been attempted then an error is thrown.*/
function transferFailed() {
  hatestatus = hatestatus & ~(UPLOAD + ABORT);
  if(hatestatus & RESTART === 0) {
    hatestatus += RESTART;
    chrome.storage.local.set({"hatestatus": hatestatus}, restart);
  } else {
    var message = "Unable to load hatedata. Status: " + interpretStatus();
    throw new Error(message);
  }
}

// h. transferCanceled()
/* This function is called if an upload from the addon data is canceled by the
 * user somehow. If a reload has not been attempted yet, then the function
 * attempts a reload. If a reload has been attempted then an error is thrown.*/
function transferCanceled() {
  hatestatus = hatestatus | ABORT;
  hatestatus = hatestatus & ~UPLOAD;
  if(hatestatus & RESTART === 0) {
    hatestatus += RESTART;
    chrome.storage.local.set({"hatestatus": hatestatus}, restart);
  } else {
    var message = "Unable to load hatedata. Status: " + interpretStatus();
    throw new Error(message);
  }
}

// i. storeHate()
/* This function is called after a successful upload of the hatebase from the
 * addon data. Additionally it is intended to only be called if it is known
 * hatedata is not stored locally. It stores hate locally*/
function storeHate() {
  if(chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError);
  } else {
    hatestatus = hatestatus | (KNOW_LOCAL + IS_LOCAL);
    hatestatus = hatestatus & ~RESTART;
    console.log("status: " + interpretStatus());
    chrome.storage.local.set({"hatestatus": hatestatus});
  }
}

// j. restart()
/* This function should only be called when attempting to reload the addon.
 * If there is an error storing hatestatus then an error is thrown.
 * If there is no error storing hatestatus then the reload occurs.*/
function restart() {
  if(chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError);
    var message = "Unable to load hatedata. Status: " + interpretStatus();
    throw new Error(message);
  } else {
    chrome.runtime.reload();
  }
}

// k. interpretStatus()
/* interprets the current hatestatus flags in an understandable way.*/
function interpretStatus(status = hatestatus) {
  var m = "";
  if(status & ON_HAND) {
    m += "hatedata is on hand, ";
  }
  if(!(status & KNOW_LOCAL)) {
    m += "whether or not hatedata is local is unknown, ";
  } else if (status & IS_LOCAL) {
    m += "hatedata is stored locally, ";
  } else {
    m += "hatedata is not stored locally, ";
  }
  if(status & UPLOAD) {
    m += "hatedata was uploaded, ";
  } else if(status & ABORT) {
    m += "hatedata upload was aborted, ";
  } else {
    m += "hatedata upload failed, ";
  }
  if(status & RESTART) {
    m += "a restart was attempted.";
  } else {
    m += "no restart.";
  }
  return m;
}

// l. uploadSuccess()
/* */
function uploadSuccess() {
  connectStart();
}

/*
 *------------------------------------------------------------------------------
 * End upload section.
 *------------------------------------------------------------------------------
 */

/*
 *------------------------------------------------------------------------------
 * 2. Content Scripts Connection
 *------------------------------------------------------------------------------
 */

var topWords = null;
var ports = {};

/* Begin organizing data and talking with any active web pages.*/
function connectStart() {
  topWords = hate.data.datapoint.filter(generateSorter({"offensiveness": 0.5}));
  chrome.browserAction.onClicked.addListener(bclickListen);
  chrome.runtime.onMessage.addListener(mainListener);
  chrome.tabs.onRemoved.addListener(removeListener);
  chrome.tabs.onUpdated.addListener(updateListener);
  chrome.tabs.onActivated.addListener(activeListener);
  chrome.tabs.query({}, insertScript);
}

function bclickListen(tab) {
  ports[tab.id.toString()].postMessage({request: "search", words: topWords});
}

/* This is the main listener of the addon.*/
function mainListener(message, sender, sendResponse) {
  if (message === null || typeof message !== 'object') {
    throw new Error("Malicious message");
  }
  if(message.hasOwnProperty("request")) {
    switch(message.request) {
      case "connect":
        var id = sender.tab.id;
        var p = chrome.tabs.connect(id, {name: id.toString()});
        ports[id.toString()] = p;
        p.onMessage.addListener(portListener);
        break;
    }
  }
}

function removeListener(tabId, removeInfo) {
  if (ports.hasOwnProperty(tabId.toString())) {
    ports[tabId.toString()].disconnect();
    delete ports[tabId.toString()];
  }
}

function updateListener(tabId, changeInfo, tab) {
  if (changeInfo.status === 'complete') {
    if (!ports.hasOwnProperty(tabId.toString())) {
      addScript(tabId);
    } else {
      chrome.tabs.query({active: true, currentWindow: true},
                        function (result) {
            if (result[0].id === tabId) {
              ports[message.port].postMessage({request: "search", words: topWords});
            }
          });
    }
  }
}

function activeListener(activeInfo) {
  if (ports.hasOwnProperty(activeInfo.tabId.toString())) {
    ports[activeInfo.tabId.toString()].postMessage({request: "search", words: topWords});
  }
}

/* Function to insert script into each page.*/
function insertScript(tbs) {
  for(let t of tbs) {
    addScript(t.id);
  }
}

function portListener(message) {
  if (message === null || typeof message !== 'object') {
    throw new Error("Malicious message");
  }
  if(message.hasOwnProperty("request")) {
    switch(message.request) {
      case "get words":
        ports[message.port].postMessage({response: "words", words: topWords});
        break;
      case "ready":
        chrome.tabs.query({active: true, currentWindow: true},
                          function (result) {
              if (result[0].id.toString() === message.port) {
                ports[message.port].postMessage({request: "search", words: topWords});
              }
            });
        break;
    }
  }
}

function addScript(tabId) {
  chrome.tabs.executeScript(tabId,
                            {file: "content_script.js"});
}

/*
 *------------------------------------------------------------------------------
 * End Content Scripts Connection
 *------------------------------------------------------------------------------
 */

 /* as of right now filters are any property of a datapoint in hbu.json
  * the relevant possibilities are as follows:
  * about_class, about_disability, about_ethnicity, about_gender,
  * about_nationality, about_religion, about_sexual_orientation, archaic,
  * number_of_variants, offensiveness, other_meaning, and small_acronym.
  *
  * support for the following filters will come soon:
  * primary_contexts, primary_location, variant_of
  *
  * the parameter filters should be an object where each key is one of the
  * property names listed above and each value is the desired value.
  *
  * the function returns a filter function so that it is easy to filter the
  * datapoint array. More explicitly if you check out this page:
  * http://www.w3schools.com/jsref/jsref_filter.asp
  * then the result of this function is what you would pass to the filter
  * function for example:
  * hate.data.datapoint.filter(generateSorter({"offensiveness": .5,
                                               "about_class": "1"}));
  * would return an array of all words in the hatebase with an offensiveness
  * greater than or equal to .5 and are about class.*/
 function generateSorter(filters) {
   return function(item) {
     for(var prop in filters) {
       switch(prop) {
         // TODO create cases for primary_contexts, primary_location
         // and variant_of.
         case "offensiveness":
           if(item[prop] < filters[prop]) {
             return false;
           }
           break;
         default:
           if(!(item[prop] === filters[prop])) {
             return false;
           }
       }
     }
     return true;
   };
 }

// 999. do stuff
bang();
<commit_msg>background.js is within 80 chars.<commit_after>/* Table of contents:
 * 1. Upload section
 *   a. globals
 *   b. bang()
 *   c. start()
 *   d. uploadHate()
 *   e. localHateGet()
 *   f. transferComplete()
 *   g. transferFailed()
 *   h. transferCanceled()
 *   i. storeHate()
 *   j. restart()
 *   k. interpretStatus()
 *   l. uploadSuccess()
 * 2. Content Scripts Connection
 * 999. do stuff*/

/*
 *------------------------------------------------------------------------------
 * 1. Upload section.
 *------------------------------------------------------------------------------
 */

// a. globals
var ON_HAND = 1;
var KNOW_LOCAL = 2;
var IS_LOCAL = 4;
var UPLOAD = 8;
var ABORT = 16;
var RESTART = 32;
var hate = null;
var hatestatus = 0;

/* 1  - is it on hand
 * 2  - do we know if it is locally stored?
 * 4  - is it locally stored?
 * 8  - was upload successful?
 * 16 - was upload aborted?
 * 32 - have we tried restarting?*/

// b. bang()
function bang() {
  chrome.storage.local.get("hatestatus", start);
}

// c. start()
/* This should be what happens first when the addon starts.*/
function start(status) {
  if(chrome.runtime.lastError) { // if we had trouble getting the status.
    console.log(chrome.runtime.lastError);
    hatestatus = hatestatus | RESTART; // assume we restarted.
  } else if(status.hasOwnProperty("hatestatus")) { // if status is local.
    hatestatus = status.hatestatus; // get most up to date status.
  } else {
    chrome.storage.local.set({"hatestatus": hatestatus});
  }
  if(hatestatus & ON_HAND === ON_HAND) {
    if(hate == null) {
      hatestatus -= ON_HAND;
    } else {
      return;
    }
  }
  if(hatestatus & (KNOW_LOCAL + IS_LOCAL) === KNOW_LOCAL) {
    uploadHate();
  } else {
    chrome.storage.local.get("hatedata", localHateGet);
  }
}

// d. uploadHate()
/* This function takes the information from hbu.json and makes it accessible
 * to the addon.*/
function uploadHate() {
  var hateURL = chrome.extension.getURL("web_source/hbu.json");
  var xobj = new XMLHttpRequest();
  xobj.addEventListener("load", transferComplete);
  xobj.addEventListener("error", transferFailed);
  xobj.addEventListener("abort", transferCanceled);
  xobj.overrideMimeType("application/json");
  xobj.open('GET', hateURL);
  xobj.send();
}

// e. localHateGet()
/* This function should only be called after an attempt to retrieve hatedata
 * locally. If the retrieval is unsuccessful for any reason it tries to
 * upload the content from the addon data. If the retrieval is successful then
 * nothing more need be done.*/
function localHateGet(data) {
  if(chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError);
    uploadHate();
  } else {
    var local = null;
    try {
      local = data.hasOwnProperty("hatedata");
    } catch (e) {
      local = false;
    }
    if(local) {
      hate = data.hatedata;
      hatestatus = hatestatus | (ON_HAND + KNOW_LOCAL + IS_LOCAL);
      hatestatus = hatestatus & ~RESTART;
      chrome.storage.local.set({"hatestatus": hatestatus});
      uploadSuccess();
    } else {
      hatestatus = hatestatus | KNOW_LOCAL;
      hatestatus = hatestatus & ~IS_LOCAL;
      uploadHate();
    }
  }
}

// f. transferComplete()
/* This function is called if an upload from the addon data is successful.
 * If hatedata is not stored locally then it attempts to store it locally.*/
function transferComplete() {
  hate = JSON.parse(this.responseText);
  hatestatus = hatestatus | (ON_HAND + UPLOAD);
  hatestatus = hatestatus & ~(ABORT + RESTART);
  chrome.storage.local.set({"hatestatus": hatestatus});
  uploadSuccess();
  if((hatestatus & (KNOW_LOCAL + IS_LOCAL)) != (KNOW_LOCAL + IS_LOCAL)) {
    chrome.storage.local.set({"hatedata": hate}, storeHate);
  }
}

// g. transferFailed()
/* This function is called if an upload from the addon data fails. If a reload
 * has not been attempted yet, then the function attempts a reload. If a reload
 * has been attempted then an error is thrown.*/
function transferFailed() {
  hatestatus = hatestatus & ~(UPLOAD + ABORT);
  if(hatestatus & RESTART === 0) {
    hatestatus += RESTART;
    chrome.storage.local.set({"hatestatus": hatestatus}, restart);
  } else {
    var message = "Unable to load hatedata. Status: " + interpretStatus();
    throw new Error(message);
  }
}

// h. transferCanceled()
/* This function is called if an upload from the addon data is canceled by the
 * user somehow. If a reload has not been attempted yet, then the function
 * attempts a reload. If a reload has been attempted then an error is thrown.*/
function transferCanceled() {
  hatestatus = hatestatus | ABORT;
  hatestatus = hatestatus & ~UPLOAD;
  if(hatestatus & RESTART === 0) {
    hatestatus += RESTART;
    chrome.storage.local.set({"hatestatus": hatestatus}, restart);
  } else {
    var message = "Unable to load hatedata. Status: " + interpretStatus();
    throw new Error(message);
  }
}

// i. storeHate()
/* This function is called after a successful upload of the hatebase from the
 * addon data. Additionally it is intended to only be called if it is known
 * hatedata is not stored locally. It stores hate locally*/
function storeHate() {
  if(chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError);
  } else {
    hatestatus = hatestatus | (KNOW_LOCAL + IS_LOCAL);
    hatestatus = hatestatus & ~RESTART;
    console.log("status: " + interpretStatus());
    chrome.storage.local.set({"hatestatus": hatestatus});
  }
}

// j. restart()
/* This function should only be called when attempting to reload the addon.
 * If there is an error storing hatestatus then an error is thrown.
 * If there is no error storing hatestatus then the reload occurs.*/
function restart() {
  if(chrome.runtime.lastError) {
    console.log(chrome.runtime.lastError);
    var message = "Unable to load hatedata. Status: " + interpretStatus();
    throw new Error(message);
  } else {
    chrome.runtime.reload();
  }
}

// k. interpretStatus()
/* interprets the current hatestatus flags in an understandable way.*/
function interpretStatus(status = hatestatus) {
  var m = "";
  if(status & ON_HAND) {
    m += "hatedata is on hand, ";
  }
  if(!(status & KNOW_LOCAL)) {
    m += "whether or not hatedata is local is unknown, ";
  } else if (status & IS_LOCAL) {
    m += "hatedata is stored locally, ";
  } else {
    m += "hatedata is not stored locally, ";
  }
  if(status & UPLOAD) {
    m += "hatedata was uploaded, ";
  } else if(status & ABORT) {
    m += "hatedata upload was aborted, ";
  } else {
    m += "hatedata upload failed, ";
  }
  if(status & RESTART) {
    m += "a restart was attempted.";
  } else {
    m += "no restart.";
  }
  return m;
}

// l. uploadSuccess()
/* */
function uploadSuccess() {
  connectStart();
}

/*
 *------------------------------------------------------------------------------
 * End upload section.
 *------------------------------------------------------------------------------
 */

/*
 *------------------------------------------------------------------------------
 * 2. Content Scripts Connection
 *------------------------------------------------------------------------------
 */

var topWords = null;
var ports = {};

/* Begin organizing data and talking with any active web pages.*/
function connectStart() {
  topWords = hate.data.datapoint.filter(generateSorter({"offensiveness": 0.5}));
  chrome.browserAction.onClicked.addListener(bclickListen);
  chrome.runtime.onMessage.addListener(mainListener);
  chrome.tabs.onRemoved.addListener(removeListener);
  chrome.tabs.onUpdated.addListener(updateListener);
  chrome.tabs.onActivated.addListener(activeListener);
  chrome.tabs.query({}, insertScript);
}

function bclickListen(tab) {
  ports[tab.id.toString()].postMessage({request: "search", words: topWords});
}

/* This is the main listener of the addon.*/
function mainListener(message, sender, sendResponse) {
  if (message === null || typeof message !== 'object') {
    throw new Error("Malicious message");
  }
  if(message.hasOwnProperty("request")) {
    switch(message.request) {
      case "connect":
        var id = sender.tab.id;
        var p = chrome.tabs.connect(id, {name: id.toString()});
        ports[id.toString()] = p;
        p.onMessage.addListener(portListener);
        break;
    }
  }
}

function removeListener(tabId, removeInfo) {
  if (ports.hasOwnProperty(tabId.toString())) {
    ports[tabId.toString()].disconnect();
    delete ports[tabId.toString()];
  }
}

function updateListener(tabId, changeInfo, tab) {
  if (changeInfo.status === 'complete') {
    if (!ports.hasOwnProperty(tabId.toString())) {
      addScript(tabId);
    } else {
      chrome.tabs.query({active: true, currentWindow: true},
                        function (result) {
            if (result[0].id === tabId) {
              ports[message.port].postMessage({request: "search",
                                               words: topWords});
            }
          });
    }
  }
}

function activeListener(activeInfo) {
  if (ports.hasOwnProperty(activeInfo.tabId.toString())) {
    ports[activeInfo.tabId.toString()].postMessage({request: "search",
                                                    words: topWords});
  }
}

/* Function to insert script into each page.*/
function insertScript(tbs) {
  for(let t of tbs) {
    addScript(t.id);
  }
}

function portListener(message) {
  if (message === null || typeof message !== 'object') {
    throw new Error("Malicious message");
  }
  if(message.hasOwnProperty("request")) {
    switch(message.request) {
      case "get words":
        ports[message.port].postMessage({response: "words", words: topWords});
        break;
      case "ready":
        chrome.tabs.query({active: true, currentWindow: true},
                          function (result) {
              if (result[0].id.toString() === message.port) {
                ports[message.port].postMessage({request: "search",
                                                 words: topWords});
              }
            });
        break;
    }
  }
}

function addScript(tabId) {
  chrome.tabs.executeScript(tabId,
                            {file: "content_script.js"});
}

/*
 *------------------------------------------------------------------------------
 * End Content Scripts Connection
 *------------------------------------------------------------------------------
 */

 /* as of right now filters are any property of a datapoint in hbu.json
  * the relevant possibilities are as follows:
  * about_class, about_disability, about_ethnicity, about_gender,
  * about_nationality, about_religion, about_sexual_orientation, archaic,
  * number_of_variants, offensiveness, other_meaning, and small_acronym.
  *
  * support for the following filters will come soon:
  * primary_contexts, primary_location, variant_of
  *
  * the parameter filters should be an object where each key is one of the
  * property names listed above and each value is the desired value.
  *
  * the function returns a filter function so that it is easy to filter the
  * datapoint array. More explicitly if you check out this page:
  * http://www.w3schools.com/jsref/jsref_filter.asp
  * then the result of this function is what you would pass to the filter
  * function for example:
  * hate.data.datapoint.filter(generateSorter({"offensiveness": .5,
                                               "about_class": "1"}));
  * would return an array of all words in the hatebase with an offensiveness
  * greater than or equal to .5 and are about class.*/
 function generateSorter(filters) {
   return function(item) {
     for(var prop in filters) {
       switch(prop) {
         // TODO create cases for primary_contexts, primary_location
         // and variant_of.
         case "offensiveness":
           if(item[prop] < filters[prop]) {
             return false;
           }
           break;
         default:
           if(!(item[prop] === filters[prop])) {
             return false;
           }
       }
     }
     return true;
   };
 }

// 999. do stuff
bang();
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var fs = require('fs');
var path = require('path');
var recast = require('recast');
var stew = require('broccoli-stew');
var funnel = require('broccoli-funnel');
var merge = require('broccoli-merge-trees');
var concat = require('broccoli-concat');
var clone = require('clone');

var header = 'import RouteRecognizer from \'ember-route-recognizer/-private/route-recognizer\';\n';
var serialized = 'var serialized = JSON.parse(\'{}\');\n'

// Grab the first object inside of the patch.
var patch;
recast.visit(recast.parse(fs.readFileSync('lib/patch.js', 'utf8')), {
  visitObjectExpression: function(path) {
    patch = path.value.properties;
    return false;
  }
});

module.exports = {
  name: 'ember-route-recognizer',

  preprocessTree: function(type, tree) {
    if (type !== 'js') { return tree; }

    // Get router.js
    var originalRouterTree = stew.find(tree, '*/router.js');
    originalRouterTree = stew.rename(originalRouterTree, 'router.js', 'router.original.js');
    // originalRouterTree = stew.map(originalRouterTree, '*/router.original.js', function(content) {
    //   content = header + content;
    //   return content;
    // });

    var modifiedRouterTree = stew.map(tree, '*/router.js', function(content) {
      // Prepend the import for the new route-recognizer.
      content = header + serialized + content;

      // Parse the AST and walk it to insert the patch.
      var ast = recast.parse(content);

      recast.visit(ast, {
        visitMemberExpression: function(path) {

          // Find `Router.map` and its arguments.
          if (path.value.property.name === 'map' && path.value.object.name === 'Router') {
            path.parentPath.replace();
          }

          // Find `Router.extend` and its arguments.
          if (path.value.property.name === 'extend' && path.value.object.property.name === 'Router') {
            var extendObject = path.parentPath.value.arguments[0];
            extendObject.properties = extendObject.properties.concat(patch);
          }

          this.traverse(path);
        }
      });

      return recast.print(ast).code;
    });

    var result = new merge([originalRouterTree, modifiedRouterTree]);

    return result;
  },

  postprocessTree: function(type, tree) {
    if (type !== 'js') { return tree; }

    var addonTree = require('broccoli-babel-transpiler')(this.treeFor('addon'), getBabelOptions(this));

    var loaderjsPath = require.resolve('loader.js');
    var loaderjsTree = new funnel(path.dirname(loaderjsPath), {
      destDir: '_precompile'
    });

    var emberPath = path.join(this.app.bowerDirectory, 'ember');
    var emberTree = new funnel(emberPath, {
      include: ['ember.prod.js'],
      destDir: '_precompile'
    });

    var configPath = path.join(this.app.name, 'config', 'environments', this.app.env + '.json');
    var configTree = this.app._configTree();
    configTree = stew.map(configTree, configPath, function(content) {
      var config = JSON.parse(content);
      var module = fs.readFileSync('lib/config-module.js', 'utf8');
      module = module.replace(/\{\{MODULE_PREFIX\}\}/g, config.modulePrefix);
      module = module.replace(/\{\{CONFIG_JSON\}\}/g, content);
      return module;
    });
    configTree = stew.find(configTree, configPath);
    configTree = stew.mv(configTree, configPath, '_precompile/config.js');

    var routerTree = stew.find(tree, '*/router.original.js');
    routerTree = stew.mv(routerTree, '*/router.original.js', '_precompile/router.js');

    var serialized;
    var precompile = new merge([loaderjsTree, emberTree, configTree, routerTree, addonTree]);
    precompile = concat(precompile, {
      outputFile: '/dummy/precompile.js',
      headerFiles: ['_precompile/loader.js'],
      footerFiles: ['_precompile/ember.prod.js', '_precompile/config.js', '_precompile/router.js'],
      inputFiles: ['**/*']
    });
    precompile = stew.map(precompile, '**/precompile.js', function(content) {
      // Patch Ember.
      content = content.replace('_initRouterJs: function () {', '_initRouterJs: function (options, recognizer) {');
      content = content.replace('new _router4.default();', 'new _router4.default(options, recognizer);');
      content = content.replace('function Router(_options)', 'function Router(_options, recognizer)');
      content = content.replace(/this.recognizer[^;]*/, 'this.recognizer = new recognizer();');

      var footer = fs.readFileSync('lib/precompile-footer.js', 'utf8');
      fs.writeFileSync('precompile.js', content + footer, 'utf8');
      serialized = require('./precompile');
      return serialized;
    });
    precompile = stew.find(precompile, '*/precompile.js');
    precompile = stew.rename(precompile, 'precompile.js', 'precompile.json');

    var result = new merge([precompile, tree]);
    result = stew.rm(result, '*/router.original.js')
    result = stew.map(result, '*/router.js', function(content) {
      content = content.replace("JSON.parse('{}')", "JSON.parse('"+serialized+"')");
      return content;
    });
    return result;
  }
};

function getBabelOptions(addonContext) {
  var options = clone(getAddonOptions(addonContext));

  // Ensure modules aren't compiled unless explicitly set to compile
  options.blacklist = options.blacklist || ['es6.modules'];

  // do not enable non-standard transforms
  if (!('nonStandard' in options)) {
    options.nonStandard = false;
  }

  // Don't include the `includePolyfill` flag, since Babel doesn't care
  delete options.includePolyfill;

  if (options.compileModules === true) {
    if (options.blacklist.indexOf('es6.modules') >= 0) {
      options.blacklist.splice(options.blacklist.indexOf('es6.modules'), 1);
    }

    delete options.compileModules;
  } else {
    if (options.blacklist.indexOf('es6.modules') < 0) {
      options.blacklist.push('es6.modules');
    }
  }

  // Ember-CLI inserts its own 'use strict' directive
  options.blacklist.push('useStrict');
  options.highlightCode = false;

  return options;
}

function getAddonOptions(addonContext) {
  var baseOptions = (addonContext.parent && addonContext.parent.options) || (addonContext.app && addonContext.app.options);
  return baseOptions && baseOptions.babel || {};
}
<commit_msg>Make it work as an addon.<commit_after>/* jshint node: true */
'use strict';

var fs = require('fs');
var path = require('path');
var recast = require('recast');
var stew = require('broccoli-stew');
var funnel = require('broccoli-funnel');
var merge = require('broccoli-merge-trees');
var concat = require('broccoli-concat');
var clone = require('clone');

var header = 'import RouteRecognizer from \'ember-route-recognizer/-private/route-recognizer\';\n';
var serialized = 'var serialized = JSON.parse(\'{}\');\n'

// Grab the first object inside of the patch.
var patch;
recast.visit(recast.parse(fs.readFileSync(__dirname + '/lib/patch.js', 'utf8')), {
  visitObjectExpression: function(path) {
    patch = path.value.properties;
    return false;
  }
});

module.exports = {
  name: 'ember-route-recognizer',

  preprocessTree: function(type, tree) {
    if (type !== 'js') { return tree; }

    // Get router.js
    var originalRouterTree = stew.find(tree, '*/router.js');
    originalRouterTree = stew.rename(originalRouterTree, 'router.js', 'router.original.js');
    // originalRouterTree = stew.map(originalRouterTree, '*/router.original.js', function(content) {
    //   content = header + content;
    //   return content;
    // });

    var modifiedRouterTree = stew.map(tree, '*/router.js', function(content) {
      // Prepend the import for the new route-recognizer.
      content = header + serialized + content;

      // Parse the AST and walk it to insert the patch.
      var ast = recast.parse(content);

      recast.visit(ast, {
        visitMemberExpression: function(path) {

          // Find `Router.map` and its arguments.
          if (path.value.property.name === 'map' && path.value.object.name === 'Router') {
            path.parentPath.replace();
          }

          // Find `Router.extend` and its arguments.
          if (path.value.property.name === 'extend' && path.value.object.property.name === 'Router') {
            var extendObject = path.parentPath.value.arguments[0];
            extendObject.properties = extendObject.properties.concat(patch);
          }

          this.traverse(path);
        }
      });

      return recast.print(ast).code;
    });

    var result = new merge([originalRouterTree, modifiedRouterTree]);

    return result;
  },

  postprocessTree: function(type, tree) {
    if (type !== 'js') { return tree; }

    var addonTree = require('broccoli-babel-transpiler')(this.treeFor('addon'), getBabelOptions(this));

    var loaderjsPath = require.resolve('loader.js');
    var loaderjsTree = new funnel(path.dirname(loaderjsPath), {
      destDir: '_precompile'
    });

    var emberPath = path.join(this.app.bowerDirectory, 'ember');
    var emberTree = new funnel(emberPath, {
      include: ['ember.prod.js'],
      destDir: '_precompile'
    });

    var config;
    var configPath = path.join(this.app.name, 'config', 'environments', this.app.env + '.json');
    var configTree = this.app._configTree();
    configTree = stew.map(configTree, configPath, function(content) {
      config = JSON.parse(content);
      var module = fs.readFileSync(__dirname + '/lib/config-module.js', 'utf8');
      module = module.replace(/\{\{MODULE_PREFIX\}\}/g, config.modulePrefix);
      module = module.replace(/\{\{CONFIG_JSON\}\}/g, content);
      return module;
    });
    configTree = stew.find(configTree, configPath);
    configTree = stew.mv(configTree, configPath, '_precompile/config.js');

    var routerTree = stew.find(tree, '*/router.original.js');
    routerTree = stew.mv(routerTree, '*/router.original.js', '_precompile/router.js');

    var serialized;
    var precompile = new merge([loaderjsTree, emberTree, configTree, routerTree, addonTree]);
    precompile = concat(precompile, {
      outputFile: 'precompile.js',
      headerFiles: ['_precompile/loader.js'],
      footerFiles: ['_precompile/ember.prod.js', '_precompile/config.js', '_precompile/router.js'],
      inputFiles: ['**/*']
    });
    precompile = stew.map(precompile, 'precompile.js', function(content) {
      // Patch Ember.
      content = content.replace('_initRouterJs: function () {', '_initRouterJs: function (options, recognizer) {');
      content = content.replace('new _router4.default();', 'new _router4.default(options, recognizer);');
      content = content.replace('function Router(_options)', 'function Router(_options, recognizer)');
      content = content.replace(/this.recognizer[^;]*/, 'this.recognizer = new recognizer();');

      var footer = fs.readFileSync(__dirname + '/lib/precompile-footer.js', 'utf8');
      footer = footer.replace('dummy/router.original', config.modulePrefix + '/router.original')
      fs.writeFileSync('precompile.js', content + footer, 'utf8');
      serialized = require(path.join(process.cwd(), '/precompile'));
      return serialized;
    });
    precompile = stew.rename(precompile, 'precompile.js', 'precompile.json');

    var result = new merge([precompile, tree]);
    result = stew.rm(result, '*/router.original.js')
    result = stew.map(result, '*/router.js', function(content) {
      content = content.replace("JSON.parse('{}')", "JSON.parse('"+serialized+"')");
      return content;
    });
    return result;
  }
};

function getBabelOptions(addonContext) {
  var options = clone(getAddonOptions(addonContext));

  // Ensure modules aren't compiled unless explicitly set to compile
  options.blacklist = options.blacklist || ['es6.modules'];

  // do not enable non-standard transforms
  if (!('nonStandard' in options)) {
    options.nonStandard = false;
  }

  // Don't include the `includePolyfill` flag, since Babel doesn't care
  delete options.includePolyfill;

  if (options.compileModules === true) {
    if (options.blacklist.indexOf('es6.modules') >= 0) {
      options.blacklist.splice(options.blacklist.indexOf('es6.modules'), 1);
    }

    delete options.compileModules;
  } else {
    if (options.blacklist.indexOf('es6.modules') < 0) {
      options.blacklist.push('es6.modules');
    }
  }

  // Ember-CLI inserts its own 'use strict' directive
  options.blacklist.push('useStrict');
  options.highlightCode = false;

  return options;
}

function getAddonOptions(addonContext) {
  var baseOptions = (addonContext.parent && addonContext.parent.options) || (addonContext.app && addonContext.app.options);
  return baseOptions && baseOptions.babel || {};
}
<|endoftext|>


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

exports.exec = async (Bastion, message) => {
  try {
    if (!Bastion.credentials.cleverbotAPIkey) {
      /**
      * Error condition is encountered.
      * @fires error
      */
      return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'noCredentials'), Bastion.strings.error(message.guild.language, 'noCredentials', true, 'Cleverbot API'), message.channel);
    }

    let guildSettings = await Bastion.db.get(`SELECT chat FROM guildSettings WHERE guildID=${message.guild.id}`);

    let color, chatStats;
    if (guildSettings.chat) {
      await Bastion.db.run(`UPDATE guildSettings SET chat=0 WHERE guildID=${message.guild.id}`);
      color = Bastion.colors.RED;
      chatStats = Bastion.strings.info(message.guild.language, 'disableChat', message.author.tag);
    }
    else {
      await Bastion.db.run(`UPDATE guildSettings SET chat=1 WHERE guildID=${message.guild.id}`);
      color = Bastion.colors.GREEN;
      chatStats = Bastion.strings.info(message.guild.language, 'enableChat', message.author.tag);
    }

    message.channel.send({
      embed: {
        color: color,
        description: chatStats
      }
    }).catch(e => {
      Bastion.log.error(e);
    });
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [],
  enabled: true
};

exports.help = {
  name: 'chat',
  botPermission: '',
  userTextPermission: 'MANAGE_GUILD',
  userVoicePermission: '',
  usage: 'chat',
  example: []
};
<commit_msg>Implemented new DB - chat command<commit_after>/**
 * @file chat command
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license MIT
 */

exports.exec = async (Bastion, message) => {
  try {
    if (!Bastion.credentials.cleverbotAPIkey) {
      /**
      * Error condition is encountered.
      * @fires error
      */
      return Bastion.emit('error', Bastion.strings.error(message.guild.language, 'noCredentials'), Bastion.strings.error(message.guild.language, 'noCredentials', true, 'Cleverbot API'), message.channel);
    }

    let guildModel = await Bastion.database.models.guild.findOne({
      attributes: [ 'chat' ],
      where: {
        guildID: message.guild.id
      }
    });

    let color, chatStats;
    if (guildModel.dataValues.chat) {
      await Bastion.database.models.guild.update({
        chat: false
      },
      {
        where: {
          guildID: message.guild.id
        },
        fields: [ 'chat' ]
      });
      color = Bastion.colors.RED;
      chatStats = Bastion.strings.info(message.guild.language, 'disableChat', message.author.tag);
    }
    else {
      await Bastion.database.models.guild.update({
        chat: true
      },
      {
        where: {
          guildID: message.guild.id
        },
        fields: [ 'chat' ]
      });
      color = Bastion.colors.GREEN;
      chatStats = Bastion.strings.info(message.guild.language, 'enableChat', message.author.tag);
    }

    message.channel.send({
      embed: {
        color: color,
        description: chatStats
      }
    }).catch(e => {
      Bastion.log.error(e);
    });
  }
  catch (e) {
    Bastion.log.error(e);
  }
};

exports.config = {
  aliases: [],
  enabled: true
};

exports.help = {
  name: 'chat',
  botPermission: '',
  userTextPermission: 'MANAGE_GUILD',
  userVoicePermission: '',
  usage: 'chat',
  example: []
};
<|endoftext|>