<commit_before>const {statSync, readFileSync} = require('fs');
const {copySync, emptyDirSync, mkdirsSync} = require('fs-extra');
const {spawnSync} = require('child_process');
const program = require('commander');
const colors = require('colors/safe');
const ignore = require('ignore');

program
  .command('build [platform]')
  .description('Builds a Tabris.js app.')
  .action(platform => build(platform));

function build(platform) {
  if (!platform) {
    fail('Missing platform');
  }
  if (!['android', 'ios', 'windows'].includes(platform)) {
    fail('Invalid platform: ' + platform);
  }
  let envVar = `TABRIS_${platform.toUpperCase()}_PLATFORM`;
  let platformSpec = process.env[envVar];
  if (!platformSpec) {
    fail('Missing cordova platform spec, expected in $' + envVar);
  }
  if (!statSafe('package.json')) {
    fail('Could not find package.json');
  }
  if (!statSafe('cordova')) {
    fail('Could not find cordova directory');
  }
  runBuildScripts(platform);
  createBuildFolder();
  copyCordova();
  copyProject();
  runInstall();
  runCordovaPlatformAdd(platformSpec);
  runCordovaBuild();
}

function createBuildFolder() {
  console.log('create build folder build/cordova');
  mkdirsSync('build');
  emptyDirSync('build/cordova');
  mkdirsSync('build/cordova/www');
}

function runBuildScripts(platform) {
  exec('npm', ['run', '--if-present', `build:${platform}`]);
  exec('npm', ['run', '--if-present', 'build']);
}

function runInstall() {
  exec('npm', ['install', '--production'], {cwd: 'build/cordova/www'});
}

function runCordovaPlatformAdd(cordovaPlatform) {
  exec('cordova', ['platform', 'add', cordovaPlatform], {cwd: 'build/cordova'});
}

function runCordovaBuild() {
  exec('cordova', ['build'], {cwd: 'build/cordova'});
}

function copyCordova() {
  copySync('cordova/', 'build/cordova/');
}

function copyProject() {
  let ig = ignore().add(['.git/', 'node_modules/', 'cordova/', 'build/', '.tabrisignore']);
  if (statSafe('.tabrisignore')) {
    ig.add(readFileSync('.tabrisignore').toString());
  }
  copySync('./', 'build/cordova/www/', {filter: (path) => {
    let stats = statSafe(path);
    let dirPath = stats && stats.isDirectory() && !path.endsWith('/') ? path + '/' : path;
    return !ig.ignores(dirPath);
  }});
}

function exec(cmd, args, opts = {}) {
  console.log('exec', `[${opts.cwd || './'}]`, cmd, args.join(' '));
  const ps = spawnSync(cmd, args, Object.assign({stdio: 'inherit'}, opts));
  if (ps.status !== 0) {
    throw new Error(`The command ${cmd} exited with ${ps.status}`);
  }
}

function statSafe(file) {
  try {
    return statSync(file);
  } catch (e) {
    return null;
  }
}

function fail(message) {
  console.error(colors.red(message));
  process.exit(1);
}
<commit_msg>Fix command execution on Windows<commit_after>const os = require('os');
const {statSync, readFileSync} = require('fs');
const {copySync, emptyDirSync, mkdirsSync} = require('fs-extra');
const {spawnSync} = require('child_process');
const program = require('commander');
const colors = require('colors/safe');
const ignore = require('ignore');

program
  .command('build [platform]')
  .description('Builds a Tabris.js app.')
  .action(platform => build(platform));

function build(platform) {
  if (!platform) {
    fail('Missing platform');
  }
  if (!['android', 'ios', 'windows'].includes(platform)) {
    fail('Invalid platform: ' + platform);
  }
  let envVar = `TABRIS_${platform.toUpperCase()}_PLATFORM`;
  let platformSpec = process.env[envVar];
  if (!platformSpec) {
    fail('Missing cordova platform spec, expected in $' + envVar);
  }
  if (!statSafe('package.json')) {
    fail('Could not find package.json');
  }
  if (!statSafe('cordova')) {
    fail('Could not find cordova directory');
  }
  runBuildScripts(platform);
  createBuildFolder();
  copyCordova();
  copyProject();
  runInstall();
  runCordovaPlatformAdd(platformSpec);
  runCordovaBuild();
}

function createBuildFolder() {
  console.log('create build folder build/cordova');
  mkdirsSync('build');
  emptyDirSync('build/cordova');
  mkdirsSync('build/cordova/www');
}

function runBuildScripts(platform) {
  exec('npm', ['run', '--if-present', `build:${platform}`]);
  exec('npm', ['run', '--if-present', 'build']);
}

function runInstall() {
  exec('npm', ['install', '--production'], {cwd: 'build/cordova/www'});
}

function runCordovaPlatformAdd(cordovaPlatform) {
  exec('cordova', ['platform', 'add', cordovaPlatform], {cwd: 'build/cordova'});
}

function runCordovaBuild() {
  exec('cordova', ['build'], {cwd: 'build/cordova'});
}

function copyCordova() {
  copySync('cordova/', 'build/cordova/');
}

function copyProject() {
  let ig = ignore().add(['.git/', 'node_modules/', 'cordova/', 'build/', '.tabrisignore']);
  if (statSafe('.tabrisignore')) {
    ig.add(readFileSync('.tabrisignore').toString());
  }
  copySync('./', 'build/cordova/www/', {filter: (path) => {
    let stats = statSafe(path);
    let dirPath = stats && stats.isDirectory() && !path.endsWith('/') ? path + '/' : path;
    return !ig.ignores(dirPath);
  }});
}

function exec(cmd, args, opts = {}) {
  let cmdName = os.platform() === 'win32' ? cmd + '.cmd' : cmd;
  console.log('exec', `[${opts.cwd || './'}]`, cmdName, args.join(' '));
  const ps = spawnSync(cmdName, args, Object.assign({stdio: 'inherit'}, opts));
  if (ps.status !== 0) {
    throw new Error(`The command ${cmd} exited with ${ps.status}`);
  }
}

function statSafe(file) {
  try {
    return statSync(file);
  } catch (e) {
    return null;
  }
}

function fail(message) {
  console.error(colors.red(message));
  process.exit(1);
}
<|endoftext|>


<commit_before>global.Thousand = 1000; //For readability of number literals in code

global.RoleObj = require('role.obj');
global.ActionObj = require('action.obj');
global.Action = {
    Harvest: require('action.harvest'),
    Feed: require('action.feed'),
    Upgrade: require('action.upgrade'),
    Build: require('action.build'),
    Withdraw: require('action.withdraw'),
    Put: require('action.put'),
    Fuel: require('action.fuel'),
    Guard: require('action.guard'),
    Pickup: require('action.pickup'),
    Drop: require('action.drop'),
    Maintain: require('action.maintain'),
    Repair: require('action.repair'),
    Recycle: require('action.recycle'),
};
global.Role = {
    Worker: require('role.worker'),
    Harvester: require('role.harvester'),
    Upgrader: require('role.upgrader'),
    Builder: require('role.builder'),
    Hauler: require('role.hauler'),
    Guardian: require('role.guardian'),
    Ant: require('role.ant'),
    Recycler: require('role.recycler'),
    Filler: require('role.filler'),
};
global.Util = {
    Spawner: require('util.spawner'),
    Tower: require('util.tower'),
    War: require('util.war'),
    Mark: require('util.mark'),
    GC: require('util.gc'),
    Smalltask: require('util.smalltask'),
    Stat: require('util.stat'),
}
global.State= {};<commit_msg>add util.construction to global<commit_after>global.Thousand = 1000; //For readability of number literals in code

global.RoleObj = require('role.obj');
global.ActionObj = require('action.obj');
global.Action = {
    Harvest: require('action.harvest'),
    Feed: require('action.feed'),
    Upgrade: require('action.upgrade'),
    Build: require('action.build'),
    Withdraw: require('action.withdraw'),
    Put: require('action.put'),
    Fuel: require('action.fuel'),
    Guard: require('action.guard'),
    Pickup: require('action.pickup'),
    Drop: require('action.drop'),
    Maintain: require('action.maintain'),
    Repair: require('action.repair'),
    Recycle: require('action.recycle'),
};
global.Role = {
    Worker: require('role.worker'),
    Harvester: require('role.harvester'),
    Upgrader: require('role.upgrader'),
    Builder: require('role.builder'),
    Hauler: require('role.hauler'),
    Guardian: require('role.guardian'),
    Ant: require('role.ant'),
    Recycler: require('role.recycler'),
    Filler: require('role.filler'),
};
global.Util = {
    Spawner: require('util.spawner'),
    Tower: require('util.tower'),
    War: require('util.war'),
    Mark: require('util.mark'),
    GC: require('util.gc'),
    Smalltask: require('util.smalltask'),
    Stat: require('util.stat'),
    Construction: require('util.construction'),
}
global.State= {};<|endoftext|>


<commit_before>var rp = require('request-promise'),
    HttpsProxyAgent = require('https-proxy-agent'),
    Promise = require('bluebird'),
    sh = require('shelljs');

const BASE_URL = "https://api.github.com/repos/";
const AUTH_URL = "https://github.com/login/oauth/authorize";
const OWNER = "Nordstrom/";
const REPO = "build-bot/";
const BASIC_AUTH = "Basic amFzb25vbG1zdGVhZDMzOkJAc2ViYWxsMzM=";
const MERGE_MESSAGE = "Merging master into branch: ";
const MASTER_MERGE_MESSAGE = "Merging into master from: ";

var Github = {
    push : function(){
        var status = sh.exec('git status', {silent : true});

    },
    preCheck : function(branch) {
        if (!branch){
            return Promise.reject("Invalid request -- need branch name")
        }

        return merge(branch, "master", MERGE_MESSAGE + branch)
            .then(function(){
                console.log("Success...");
            })
            .catch(function(err){
                if (err.message.message.indexOf("409")){
                    return Promise.reject("Conflict merging master into " + branch);
                } else {
                    return Promise.reject(err.message);
                }
            })
    },

    mergeToMaster : function(branch){
        if (!branch){
            return Promise.reject("Invalid request -- need branch name")
        }

        return merge("master", branch, MASTER_MERGE_MESSAGE + branch)
            .then(function(){
                console.log("Success...");
            })
            .catch(function(err){
                if (err.message.message.indexOf("409")){
                    return Promise.reject("Conflict merging " + branch + "into master");
                } else {
                    return Promise.reject(err.message);
                }
            })
    }
};

module.exports = Github;

function merge(base, head, message){
    if (!base || !head || !message){
        return Promise.reject("Invalid request, cant merge")
    }

    var params = {
        uri : BASE_URL + OWNER + REPO + "merges",
        method : "POST",
        json : true,
        headers : {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "User-Agent" : "Hackathon-Local-Dev",
            "Authorization" : BASIC_AUTH
        },
        body : {
            "base": base,
            "head": head,
            "commit_message": message
        }
    };

    params = checkProxy(params);

    return rp(params);
}

function checkProxy(params){
    if (!!process.env.LOCAL){
        params.agent = new HttpsProxyAgent("http://webproxysea.nordstrom.net:8181");
    }
    return params;
}

//** TEST CODE ****/
Github.push();
<commit_msg>auto push from bot<commit_after>var rp = require('request-promise'),
    HttpsProxyAgent = require('https-proxy-agent'),
    Promise = require('bluebird'),
    sh = require('shelljs');

const BASE_URL = "https://api.github.com/repos/";
const AUTH_URL = "https://github.com/login/oauth/authorize";
const OWNER = "Nordstrom/";
const REPO = "build-bot/";
const BASIC_AUTH = "Basic amFzb25vbG1zdGVhZDMzOkJAc2ViYWxsMzM=";
const MERGE_MESSAGE = "Merging master into branch: ";
const MASTER_MERGE_MESSAGE = "Merging into master from: ";

var Github = {
    push : function(){
        var code = sh.exec('git add .', {silent : true});
        if (code == 1){
            return Promise.reject("Error on git add");
        }
        code = sh.exec('git commit -m "auto push from bot"');
        if (code == 1){
            return Promise.reject("Error on git commit");
        }

    },
    preCheck : function(branch) {
        if (!branch){
            return Promise.reject("Invalid request -- need branch name")
        }

        return merge(branch, "master", MERGE_MESSAGE + branch)
            .then(function(){
                console.log("Success...");
            })
            .catch(function(err){
                if (err.message.message.indexOf("409")){
                    return Promise.reject("Conflict merging master into " + branch);
                } else {
                    return Promise.reject(err.message);
                }
            })
    },

    mergeToMaster : function(branch){
        if (!branch){
            return Promise.reject("Invalid request -- need branch name")
        }

        return merge("master", branch, MASTER_MERGE_MESSAGE + branch)
            .then(function(){
                console.log("Success...");
            })
            .catch(function(err){
                if (err.message.message.indexOf("409")){
                    return Promise.reject("Conflict merging " + branch + "into master");
                } else {
                    return Promise.reject(err.message);
                }
            })
    }
};

module.exports = Github;

function merge(base, head, message){
    if (!base || !head || !message){
        return Promise.reject("Invalid request, cant merge")
    }

    var params = {
        uri : BASE_URL + OWNER + REPO + "merges",
        method : "POST",
        json : true,
        headers : {
            "Accept": "application/json",
            "Content-Type": "application/json",
            "User-Agent" : "Hackathon-Local-Dev",
            "Authorization" : BASIC_AUTH
        },
        body : {
            "base": base,
            "head": head,
            "commit_message": message
        }
    };

    params = checkProxy(params);

    return rp(params);
}

function checkProxy(params){
    if (!!process.env.LOCAL){
        params.agent = new HttpsProxyAgent("http://webproxysea.nordstrom.net:8181");
    }
    return params;
}

//** TEST CODE ****/
Github.push();
<|endoftext|>


<commit_before>import giturl from "git-url-parse";
import _ from "lodash";

import GitHub from "github";

import pkg from "../package.json";
import { toMarkdown, toTextTable } from "./compare";
import rpt from "./promise/read-package-tree";

function toTag(tags, version) {
    let v = `v${version}`;
    if (tags.has(v)) {
        return v;
    }
    return tags.has(version) && version;
}

function diffURL(cm, to) {
    if (cm.repo) {
        if (cm.current === to) {
            let tag = toTag(cm.tags, cm.current);
            return tag && `${cm.repo}/tree/${tag}`;
        }
        let ft = toTag(cm.tags, cm.current);
        let tt = toTag(cm.tags, to);
        return ft && tt && `${cm.repo}/compare/${ft}...${tt}`;
    }
    return "";
}

function versionRange(current, to) {
    if (current === to) {
        return current;
    }
    return `${current}...${to}`;
}

class CompareModel {
    constructor(a) {
        [this.name, this.current, this.wanted, this.latest, this.packageType] = a;
        this.repo = "";
        this.homepage = "";
        this.tags = new Set();
    }

    rangeWanted() {
        return versionRange(this.current, this.wanted);
    }

    rangeLatest() {
        return versionRange(this.current, this.latest);
    }

    diffWantedURL() {
        return diffURL(this, this.wanted);
    }

    diffLatestURL() {
        return diffURL(this, this.latest);
    }
}

function selectGetTagsPromise(LOG, github, c) {
    let handler = (prev, res) => {
        let tags = prev.concat(res.map(t => t.ref.split("/")[2]));
        if (github.hasNextPage(res)) {
            return github.getNextPage(res).then(r => handler(tags, r));
        }
        return tags;
    };
    if (c.repo) {
        let url = giturl(c.repo);
        if (url.owner && url.name) {
            LOG(`BEGIN getTags from ${url.toString("https")}`);
            return Promise.all([
                github.gitdata.getTags({ owner: url.owner, repo: url.name })
                    .then(res => handler([], res))
            ]).then(([tags]) => {
                LOG(`END   getTags ${tags}`);
                c.tags = new Set(tags);
                return c;
            });
        }
    }
    return Promise.resolve(c);
}

function reconcile(LOG, github, dep, c) {
    LOG(`BEGIN reconcile CompareModel ${c.name}`);
    c.homepage = dep.homepage;
    if (dep.repository) {
        if (dep.repository.url) {
            let u = giturl(dep.repository.url);
            c.repo = u && u.toString("https");
        }
        if (_.isString(dep.repository) && 2 === dep.split("/")) {
            c.repo = `https://github.com/${dep.repository}`;
        }
    }
    return c.shadow ? Promise.resolve(c) : selectGetTagsPromise(LOG, github, c).then(c => {
        LOG(`END   reconcile CompareModel ${c.name}`);
        return c;
    });
}

function toCompareModels(LOG, github, cwd, diff) {
    let map = new Map(diff.map(d => {
        let c = new CompareModel(d);
        return [c.name, c];
    }));
    LOG("BEGIN read-package-tree");
    return rpt(cwd, (n, k) => map.get(k)).then(data => {
        LOG("END   read-package-tree");
        let ps = data.children.map(e => reconcile(LOG, github, e.package, map.get(e.package.name)));
        return Promise.all(ps).then(() => map);
    });
}

// for tesing purpose
export const __test__ = [CompareModel, diffURL, toTag, versionRange];

export default class {
    constructor(options, remote) {
        this.options = options;
        this.LOG = options.logger;
        this.url = giturl(remote);
        let ghopt = {
            headers: {
                "user-agent": `${pkg.name}/${pkg.version}`
            }
        };
        if (this.url.resource !== "github.com") {
            // for GHE
            ghopt.host = this.url.resource;
            ghopt.pathPrefix = "/api/v3";
        }
        this.original = new GitHub(ghopt);
        this.original.authenticate({
            type: "token", token: options.token
        });
    }

    pullRequest(baseBranch, newBranch, diff) {
        this.LOG(`prepare PullRequest ${this.url.toString("https")} ${baseBranch}...${newBranch}`);
        if (this.options.execute) {
            this.LOG("Create Markdown Report for PullRequest.");
            return toCompareModels(this.LOG, this.original, this.options.workingdir, diff)
                .then(toMarkdown)
                .then(view => {
                    return {
                        owner: this.url.owner,
                        repo: this.url.name,
                        base: baseBranch,
                        head: newBranch,
                        title: `update dependencies at ${this.options.now}`,
                        body: view
                    };
                }).then(value => {
                    this.LOG("BEGIN Send PullRequest.");
                    return this.original.pullRequests.create(value).then(body => {
                        this.LOG(`END   Send PullRequest. ${body.html_url}`);
                    });
                });
        } else {
            this.LOG("Sending PullRequest is skipped because --execute is not specified.");
            return toCompareModels(this.LOG, this.original, this.options.workingdir, diff)
                .then(toTextTable);
        }
    }
}
<commit_msg>suppress error on getTags<commit_after>import giturl from "git-url-parse";
import _ from "lodash";

import GitHub from "github";

import pkg from "../package.json";
import { toMarkdown, toTextTable } from "./compare";
import rpt from "./promise/read-package-tree";

function toTag(tags, version) {
    let v = `v${version}`;
    if (tags.has(v)) {
        return v;
    }
    return tags.has(version) && version;
}

function diffURL(cm, to) {
    if (cm.repo) {
        if (cm.current === to) {
            let tag = toTag(cm.tags, cm.current);
            return tag && `${cm.repo}/tree/${tag}`;
        }
        let ft = toTag(cm.tags, cm.current);
        let tt = toTag(cm.tags, to);
        return ft && tt && `${cm.repo}/compare/${ft}...${tt}`;
    }
    return "";
}

function versionRange(current, to) {
    if (current === to) {
        return current;
    }
    return `${current}...${to}`;
}

class CompareModel {
    constructor(a) {
        [this.name, this.current, this.wanted, this.latest, this.packageType] = a;
        this.repo = "";
        this.homepage = "";
        this.tags = new Set();
    }

    rangeWanted() {
        return versionRange(this.current, this.wanted);
    }

    rangeLatest() {
        return versionRange(this.current, this.latest);
    }

    diffWantedURL() {
        return diffURL(this, this.wanted);
    }

    diffLatestURL() {
        return diffURL(this, this.latest);
    }
}

function selectGetTagsPromise(LOG, github, c) {
    let handler = (prev, res) => {
        let tags = prev.concat(res.map(t => t.ref.split("/")[2]));
        if (github.hasNextPage(res)) {
            return github.getNextPage(res).then(r => handler(tags, r));
        }
        return tags;
    };
    if (c.repo) {
        let url = giturl(c.repo);
        if (url.owner && url.name) {
            LOG(`BEGIN getTags from ${url.toString("https")}`);
            return Promise.all([
                github.gitdata.getTags({ owner: url.owner, repo: url.name })
                    .then(res => handler([], res))
            ]).then(([tags]) => {
                LOG(`END   getTags ${tags}`);
                c.tags = new Set(tags);
                return c;
            }, err => {
                LOG(`END   getTags ${err}`);
                return c;
            });
        }
    }
    return Promise.resolve(c);
}

function reconcile(LOG, github, dep, c) {
    LOG(`BEGIN reconcile CompareModel ${c.name}`);
    c.homepage = dep.homepage;
    if (dep.repository) {
        if (dep.repository.url) {
            let u = giturl(dep.repository.url);
            c.repo = u && u.toString("https");
        }
        if (_.isString(dep.repository) && 2 === dep.split("/")) {
            c.repo = `https://github.com/${dep.repository}`;
        }
    }
    return c.shadow ? Promise.resolve(c) : selectGetTagsPromise(LOG, github, c).then(c => {
        LOG(`END   reconcile CompareModel ${c.name}`);
        return c;
    });
}

function toCompareModels(LOG, github, cwd, diff) {
    let map = new Map(diff.map(d => {
        let c = new CompareModel(d);
        return [c.name, c];
    }));
    LOG("BEGIN read-package-tree");
    return rpt(cwd, (n, k) => map.get(k)).then(data => {
        LOG("END   read-package-tree");
        let ps = data.children.map(e => reconcile(LOG, github, e.package, map.get(e.package.name)));
        return Promise.all(ps).then(() => map);
    });
}

// for tesing purpose
export const __test__ = [CompareModel, diffURL, toTag, versionRange];

export default class {
    constructor(options, remote) {
        this.options = options;
        this.LOG = options.logger;
        this.url = giturl(remote);
        let ghopt = {
            headers: {
                "user-agent": `${pkg.name}/${pkg.version}`
            }
        };
        if (this.url.resource !== "github.com") {
            // for GHE
            ghopt.host = this.url.resource;
            ghopt.pathPrefix = "/api/v3";
        }
        this.original = new GitHub(ghopt);
        this.original.authenticate({
            type: "token", token: options.token
        });
    }

    pullRequest(baseBranch, newBranch, diff) {
        this.LOG(`prepare PullRequest ${this.url.toString("https")} ${baseBranch}...${newBranch}`);
        if (this.options.execute) {
            this.LOG("Create Markdown Report for PullRequest.");
            return toCompareModels(this.LOG, this.original, this.options.workingdir, diff)
                .then(toMarkdown)
                .then(view => {
                    return {
                        owner: this.url.owner,
                        repo: this.url.name,
                        base: baseBranch,
                        head: newBranch,
                        title: `update dependencies at ${this.options.now}`,
                        body: view
                    };
                }).then(value => {
                    this.LOG("BEGIN Send PullRequest.");
                    return this.original.pullRequests.create(value).then(body => {
                        this.LOG(`END   Send PullRequest. ${body.html_url}`);
                    });
                });
        } else {
            this.LOG("Sending PullRequest is skipped because --execute is not specified.");
            return toCompareModels(this.LOG, this.original, this.options.workingdir, diff)
                .then(toTextTable);
        }
    }
}
<|endoftext|>


<commit_before>/**
 * An FP style framework of data manipulate in javascript.
 */
(function()
{
	var ROOT = (typeof global === "object" && global) || this;

	function Pond()
	{
		this.downstream = null;
	}
	Pond.prototype.accept = function(data) // Boolean
	{
	};
	Pond.prototype.end = function() // Void
	{
	};

	function Desilter()
	{
		this.sediment = this.settle();
	}
	Desilter.prototype = new Pond();
	Desilter.prototype.settle = function() // Sediment
	{
		return [];
	};

	// Intermediate Operators

	function FilterOp(pred)
	{
		this.pred = pred;
	}
	FilterOp.prototype = new Pond();
	FilterOp.prototype.accept = function(d)
	{
		if (this.pred(d))
		{
			return this.downstream.accept(d);
		}
		else
		{
			return true;
		}
	};

	function MapOp(fn)
	{
		this.fn = fn;
	}
	MapOp.prototype = new Pond();
	MapOp.prototype.accept = function(d)
	{
		return this.downstream.accept(this.fn(d));
	};

	// Terminate Operators

	function Terminator()
	{
	}
	Terminator.prototype = new Desilter();
	Terminator.prototype.get = function()
	{
		return this.sediment;
	};

	function TakeOp(num)
	{
		this.num = num;
	}
	TakeOp.prototype = new Terminator();
	TakeOp.prototype.accept = function(d)
	{
		if (this.sediment.length < this.num)
		{
			this.sediment.push(d);
			return true;
		}
		else
		{
			return false;
		}
	};
	TakeOp.prototype.settle = function()
	{
		return [];
	};

	function Canal()
	{
		var self = this;
		var head = null;
		var tail = null;
		var data = null;

		var add = function(pond)
		{
			if (head == null)
			{
				head = pond;
			}
			if (tail != null)
			{
				tail.downstream = pond;
			}
			tail = pond;
			return self;
		};

		this.source = function() //
		{
			if (arguments.length > 0)
			{
				data = arguments[0];
				return self;
			}
			else
			{
				return data;
			}
		};

		// Intermediate Operations

		this.filter = function(pred)
		{
			return add(new FilterOp(pred));
		};

		this.map = function(fn)
		{
			return add(new MapOp(fn));
		};

		// Terminate Operations

		this.evaluate = function(source)
		{
			if (source != null)
			{
				for (i in source)
				{
					if (!head.accept(source[i]))
					{
						break;
					}
				}
				return tail.get();
			}
			else
			{
				return undefined;
			}
		};

		this.take = function(num)
		{
			add(new TakeOp(num));
			return this.evaluate(data);
		};
	}

	Canal.of = function(data)
	{
		return new Canal().source(data);
	};

	ROOT.Canal = Canal;

}.call(this));
<commit_msg>Canal is implemented with Ops and Ponds now.<commit_after>/**
 * Functional Programming Framework of Calculation in Javascript.
 * https://github.com/KerneLab/Canal
 */
(function()
{
	var ROOT = (typeof global === "object" && global) || this;

	function Pond()
	{
		this.downstream = null;
	}
	Pond.prototype.begin = function() // Void
	{
		if (this.downstream != null)
		{
			this.downstream.begin();
		}
	};
	Pond.prototype.accept = function(data) // Boolean
	{
	};
	Pond.prototype.done = function() // Void
	{
		if (this.downstream != null)
		{
			this.downstream.done();
		}
	};

	function Desilter()
	{
		this.sediment = undefined;
	}
	Desilter.prototype = new Pond();
	Desilter.prototype.settling = null; // () -> new Sediment
	Desilter.prototype.begin = function()
	{
		if (this.settling != null)
		{
			this.settle(this.settling());
		}
		if (this.downstream != null)
		{
			this.downstream.begin();
		}
	};
	Desilter.prototype.settle = function() // access Sediment
	{
		if (arguments.length > 0)
		{
			this.sediment = arguments[0];
			return this;
		}
		else
		{
			return this.sediment;
		}
	};

	function Grouper()
	{
	}
	Grouper.prototype = new Desilter();
	Grouper.prototype.settling = function()
	{
		return {};
	};
	Grouper.prototype.keyOf = function(d)
	{

	};
	Grouper.prototype.valOf = function(d)
	{
		return d;
	};
	Grouper.prototype.accept = function(d)
	{
		var key = this.keyOf(d);
		var settle = this.settle();
		var group = settle[key];
		if (group == null)
		{
			group = [];
			settle[key] = group;
		}
		group.push(this.valOf(d));
		return true;
	};
	Grouper.prototype.done = function()
	{
		if (this.downstream != null)
		{
			var settle = this.settle();

			for (group in settle)
			{
				if (!this.downstream.accept([ group, settle[group] ]))
				{
					break;
				}
			}

			this.downstream.done();
		}
	};

	// Operators

	function Operator()
	{
		this.upstream = null;
	}
	Operator.prototype.newPond = function() // () -> Pond
	{
		return new Pond();
	};

	// Intermediate Operators

	function DistinctOp(cmp)
	{
		cmp = cmp != null // (a,b) -> 0(=)
		? cmp : function(a, b)
		{
			return a == b ? 0 : 1;
		};

		function DistinctPond()
		{
		}
		DistinctPond.prototype = new Desilter();
		DistinctPond.prototype.settling = function()
		{
			return [];
		};
		DistinctPond.prototype.accept = function(d)
		{
			var found = false;
			var settle = this.settle();
			for (i in settle)
			{
				if (cmp(settle[i], d) == 0)
				{
					found = true;
					break;
				}
			}
			if (!found)
			{
				settle.push(d);
			}
			return true;
		};
		DistinctPond.prototype.done = function()
		{
			if (this.downstream != null)
			{
				var settle = this.settle();
				for (i in settle)
				{
					if (!this.downstream.accept(settle[i]))
					{
						break;
					}
				}
				this.downstream.done();
			}
		};

		this.newPond = function()
		{
			return new DistinctPond();
		};
	}
	DistinctOp.prototype = new Operator();

	function FilterOp(pred)
	{
		function FilterPond()
		{
		}
		FilterPond.prototype = new Pond();
		FilterPond.prototype.accept = function(d)
		{
			if (pred(d))
			{
				return this.downstream.accept(d);
			}
			else
			{
				return true;
			}
		};

		this.newPond = function()
		{
			return new FilterPond();
		};
	}
	FilterOp.prototype = new Operator();

	function FlatMapOp(fn)
	{
		function FlatMapPond()
		{
		}
		FlatMapPond.prototype = new Pond();
		FlatMapPond.prototype.accept = function(d)
		{
			var data = fn(d);
			if (data instanceof Array)
			{
				for (i in data)
				{
					if (!this.downstream.accept(data[i]))
					{
						return false;
					}
				}
				return true;
			}
			else
			{
				return this.downstream.accept(data);
			}
		};

		this.newPond = function()
		{
			return new FlatMapPond();
		};
	}
	FlatMapOp.prototype = new Operator();

	function ForeachOp(fn) // (data) -> Void
	{
		function ForeachPond()
		{
		}
		ForeachPond.prototype = new Pond();
		ForeachPond.prototype.accept = function(d)
		{
			fn(d);
			return this.downstream.accept(d);
		};

		this.newPond = function()
		{
			return new ForeachPond();
		}
	}
	ForeachOp.prototype = new Operator();

	function GroupOp(key, val) // (data) -> key, [(data) -> val]
	{
		function GroupPond()
		{
		}
		GroupPond.prototype = new Grouper();
		GroupPond.prototype.keyOf = function(d)
		{
			return key(d);
		};
		GroupPond.prototype.valOf = function(d)
		{
			return val == null ? d : val(d);
		};

		this.newPond = function()
		{
			return new GroupPond();
		};
	}
	GroupOp.prototype = new Operator();

	function JoinOp(canal, keyL, keyR)
	{
		keyL = keyL != null ? keyL : function(d)
		{
			return d[0];
		};
		keyR = keyR != null ? keyR : function(d)
		{
			return d[0];
		};

		function JoinPond()
		{

		}
		JoinPond.prototype = new Grouper();
		JoinPond.prototype.keyOf = function(d)
		{
			return keyL(d);
		};
		JoinPond.prototype.done = function()
		{
			if (this.downstream != null)
			{
				var left = this.settle();
				var rightData = canal.groupBy(keyR, null).collect();
				var right = {};
				for (i in rightData)
				{
					var d = rightData[i];
					right[d[0]] = d[1];
				}

				out: for (k in left)
				{
					var ls = left[k];
					if (ls != null)
					{
						var rs = right[k];
						if (rs != null)
						{
							for (l in ls)
							{
								for (r in rs)
								{
									if (!this.downstream.accept([ ls[l][1],
											rs[r][1] ]))
									{
										break out;
									}
								}
							}
						}
					}
				}

				this.downstream.done();
			}
		};

		this.newPond = function()
		{
			return new JoinPond();
		};
	}
	JoinOp.prototype = new Operator();

	function MapOp(fn)
	{
		function MapPond()
		{
		}
		MapPond.prototype = new Pond();
		MapPond.prototype.accept = function(d)
		{
			return this.downstream.accept(fn(d));
		};

		this.newPond = function()
		{
			return new MapPond();
		};
	}
	MapOp.prototype = new Operator();

	function MapValuesOp(fn) // ([val..]) -> Value
	{
		function MapValuesPond()
		{
		}
		MapValuesPond.prototype = new Pond();
		MapValuesPond.prototype.accept = function(d)
		{
			return this.downstream.accept([ d[0], fn(d[1]) ]);
		};

		this.newPond = function()
		{
			return new MapValuesPond();
		};
	}
	MapValuesOp.prototype = new Operator();

	function SortOp(cmp) // (a,b) -> 0(=) -1(<) 1(>)
	{
		function SortPond()
		{
		}
		SortPond.prototype = new Desilter();
		SortPond.prototype.settling = function()
		{
			return [];
		};
		SortPond.prototype.accept = function(d)
		{
			this.settle().push(d);
			return true;
		};
		SortPond.prototype.done = function(d)
		{
			if (this.downstream != null)
			{
				var settle = this.settle();
				if (cmp != null)
				{
					settle.sort(cmp);
				}
				else
				{
					settle.sort();
				}
				for (i in settle)
				{
					if (!this.downstream.accept(settle[i]))
					{
						break;
					}
				}
				this.downstream.done();
			}
		};

		this.newPond = function()
		{
			return new SortPond();
		};
	}
	SortOp.prototype = new Operator();

	// Terminate Operators

	function Terminal()
	{
	}
	Terminal.prototype = new Desilter();
	Terminal.prototype.get = function()
	{
		return this.settle();
	};

	function CollectOp()
	{
		function CollectPond()
		{
		}
		CollectPond.prototype = new Terminal();
		CollectPond.prototype.settling = function()
		{
			return [];
		}
		CollectPond.prototype.accept = function(d)
		{
			this.settle().push(d);
			return true;
		};

		this.newPond = function()
		{
			return new CollectPond();
		}
	}
	CollectOp.prototype = new Operator();

	function ReduceOp(init, reducer) // (res,data) -> res
	{
		function ReducePond()
		{
		}
		ReducePond.prototype = new Terminal();
		ReducePond.prototype.settling = function()
		{
			return init;
		};
		ReducePond.prototype.accept = function(d)
		{
			this.settle(reducer(this.settle(), d));
			return true;
		};

		this.newPond = function()
		{
			return new ReducePond();
		};
	}
	ReduceOp.prototype = new Operator();

	function TakeOp(num)
	{
		function TakePond()
		{
		}
		TakePond.prototype = new Terminal();
		TakePond.prototype.settling = function()
		{
			return [];
		};
		TakePond.prototype.accept = function(d)
		{
			if (this.settle().length < num)
			{
				this.settle().push(d);
				return true;
			}
			else
			{
				return false;
			}
		};

		this.newPond = function()
		{
			return new TakePond();
		};
	}
	TakeOp.prototype = new Operator();

	function Canal()
	{
		var self = this;
		var tail = null;
		var data = null;

		var chain = function(pond)
		{
			for (prev = tail; prev != null; prev = prev.upstream)
			{
				var temp = prev.newPond();
				temp.downstream = pond;
				pond = temp;
			}
			return pond;
		};

		var calc = function(entr, data)
		{
			entr.begin();

			for (i in data)
			{
				if (!entr.accept(data[i]))
				{
					break;
				}
			}

			entr.done();
		};

		this.evaluate = function(op) // T -> Value
		{
			if (op != null)
			{
				var data = arguments.length > 1 ? arguments[1] : this.source();

				if (data != null)
				{
					var pond = op.newPond();

					calc(chain(pond), data);

					return pond.get();
				}
				else
				{
					return undefined;
				}
			}
			else
			{
				return undefined;
			}
		};

		this.add = function(op)
		{
			op.upstream = tail;
			tail = op;
			return self;
		};

		this.source = function() // access data
		{
			if (arguments.length > 0)
			{
				data = arguments[0];
				return self;
			}
			else
			{
				return data;
			}
		};

		// Intermediate Operations

		this.distinct = function()
		{
			return this.add(new DistinctOp(arguments[0]));
		}

		this.filter = function(pred)
		{
			return this.add(new FilterOp(pred));
		};

		this.flatMap = function(fn)
		{
			return this.add(new FlatMapOp(fn));
		};

		this.foreach = function(fn)
		{
			return this.add(new ForeachOp(fn));
		};

		this.groupBy = function(key)
		{
			return this.add(new GroupOp(key,
					arguments.length > 1 ? arguments[1] : null));
		};

		this.join = function(canal)
		{
			return this.add(new JoinOp(canal, arguments[1], arguments[2]));
		};

		this.map = function(fn)
		{
			return this.add(new MapOp(fn));
		};

		this.mapValues = function(fn)
		{
			return this.add(new MapValuesOp(fn));
		};

		this.sort = function()
		{
			return this.add(new SortOp(arguments.length > 0 ? arguments[0]
					: null));
		};

		// Terminate Operations

		this.collect = function()
		{
			return this.evaluate(new CollectOp());
		};

		this.count = function()
		{
			return this.map(function(d)
			{
				return 1;
			}).evaluate(new ReduceOp(0, function(res, dat)
			{
				return res + dat;
			}));
		};

		this.reduce = function(init, reducer)
		{
			return this.evaluate(new ReduceOp(init, reducer));
		};

		this.take = function(num)
		{
			return this.evaluate(new TakeOp(num));
		};
	}

	Canal.of = function(data)
	{
		return new Canal().source(data);
	};

	ROOT.Canal = Canal;

}.call(this));
<|endoftext|>


<commit_before>/**
 * # A working Bar Chart
 *
 * To see this chart run `gulp connect` and then navigate to localhost:1337.
 * The js file that renders this chart is found `www > js > main.js`
 */
koto.chart('BarChart', function (Chart) {
	return class Donut extends Chart {
		constructor(selection) {
			super(selection);

			// Setup
			var chart = this;
			this.config('width', 800);
			this.config('height', 500);

			// Scales
			chart.x = d3.scale.linear()
				.range([0, this.config('width')]);

			chart.y = d3.scale.linear()
				.domain([0, 100])
				.rangeRound([0, this.config('height')]);

			// Layer
			chart.layer('bars', this.base.append('g'), {
				dataBind: function dataBind(data) {
					return this.selectAll('rect')
						.data(data, function(d) { return d.time; });
				},
				insert: function insert() {
					return this.append('rect');
				}
			})
			.on('enter', function() {
				var length = this.data().length;
				this.attr('x', function(d, i) { return chart.x(i + 1) - 0.5; })
					.attr('y', function(d) { return chart.config('height') - chart.y(d.value) - 0.5; })
					.attr('width', chart.config('width') / length)
					.style('fill', 'steelBlue')
					.attr('height', function(d) { return chart.y(d.value); });
			})
			.on('enter:transition', function() {
				this.duration(1000)
					.attr('x', function(d, i) { return chart.x(i) - 0.5; });
			})
			.on('update:transition', function() {
				this.duration(1000)
					.attr('x', function(d, i) { return chart.x(i) - 0.5; });
			})
			.on('exit:transition', function() {
				this.duration(1000)
					.attr('x', function(d, i) { return chart.x(i - 1) - 0.5; })
					.remove();
			});
		}
		//override methods
		preDraw(data) {
			this.x.domain([0, data.length]);
		}
	};
});
<commit_msg>Fix chart name<commit_after>/**
 * # A working Bar Chart
 *
 * To see this chart run `gulp connect` and then navigate to localhost:1337.
 * The js file that renders this chart is found `www > js > main.js`
 */
koto.chart('BarChart', function (Chart) {
	return class BarChart extends Chart {
		constructor(selection) {
			super(selection);

			// Setup
			var chart = this;
			this.config('width', 800);
			this.config('height', 500);

			// Scales
			chart.x = d3.scale.linear()
				.range([0, this.config('width')]);

			chart.y = d3.scale.linear()
				.domain([0, 100])
				.rangeRound([0, this.config('height')]);

			// Layer
			chart.layer('bars', this.base.append('g'), {
				dataBind: function dataBind(data) {
					return this.selectAll('rect')
						.data(data, function(d) { return d.time; });
				},
				insert: function insert() {
					return this.append('rect');
				}
			})
			.on('enter', function() {
				var length = this.data().length;
				this.attr('x', function(d, i) { return chart.x(i + 1) - 0.5; })
					.attr('y', function(d) { return chart.config('height') - chart.y(d.value) - 0.5; })
					.attr('width', chart.config('width') / length)
					.style('fill', 'steelBlue')
					.attr('height', function(d) { return chart.y(d.value); });
			})
			.on('enter:transition', function() {
				this.duration(1000)
					.attr('x', function(d, i) { return chart.x(i) - 0.5; });
			})
			.on('update:transition', function() {
				this.duration(1000)
					.attr('x', function(d, i) { return chart.x(i) - 0.5; });
			})
			.on('exit:transition', function() {
				this.duration(1000)
					.attr('x', function(d, i) { return chart.x(i - 1) - 0.5; })
					.remove();
			});
		}
		//override methods
		preDraw(data) {
			this.x.domain([0, data.length]);
		}
	};
});
<|endoftext|>


<commit_before>var utils = require('./utils')

function Chunk (uploader, file, offset) {
  utils.defineNonEnumerable(this, 'uploader', uploader)
  utils.defineNonEnumerable(this, 'file', file)
  utils.defineNonEnumerable(this, 'bytes', null)
  this.offset = offset
  this.tested = false
  this.retries = 0
  this.pendingRetry = false
  this.preprocessState = 0
  this.readState = 0
  this.loaded = 0
  this.total = 0
  this.chunkSize = this.uploader.opts.chunkSize
  this.startByte = this.offset * this.chunkSize
  this.endByte = this.computeEndByte()
  this.xhr = null
}

var STATUS = Chunk.STATUS = {
  PENDING: 'pending',
  UPLOADING: 'uploading',
  READING: 'reading',
  SUCCESS: 'success',
  ERROR: 'error',
  COMPLETE: 'complete',
  PROGRESS: 'progress',
  RETRY: 'retry'
}

utils.extend(Chunk.prototype, {

  _event: function (evt, args) {
    args = utils.toArray(arguments)
    args.unshift(this)
    this.file._chunkEvent.apply(this.file, args)
  },

  computeEndByte: function () {
    var endByte = Math.min(this.file.size, (this.offset + 1) * this.chunkSize)
    if (this.file.size - endByte < this.chunkSize && !this.uploader.opts.forceChunkSize) {
      // The last chunk will be bigger than the chunk size,
      // but less than 2 * this.chunkSize
      endByte = this.file.size
    }
    return endByte
  },

  getParams: function () {
    return {
      chunkNumber: this.offset + 1,
      chunkSize: this.uploader.opts.chunkSize,
      currentChunkSize: this.endByte - this.startByte,
      totalSize: this.file.size,
      identifier: this.file.uniqueIdentifier,
      filename: this.file.name,
      relativePath: this.file.relativePath,
      totalChunks: this.file.chunks.length
    }
  },

  getTarget: function (target, params) {
    if (!params.length) {
      return target
    }
    if (target.indexOf('?') < 0) {
      target += '?'
    } else {
      target += '&'
    }
    return target + params.join('&')
  },

  test: function () {
    this.xhr = new XMLHttpRequest()
    this.xhr.addEventListener('load', testHandler, false)
    this.xhr.addEventListener('error', testHandler, false)
    var testMethod = utils.evalOpts(this.uploader.opts.testMethod, this.file, this)
    var data = this.prepareXhrRequest(testMethod, true)
    this.xhr.send(data)

    var $ = this
    function testHandler (event) {
      var status = $.status(true)
      if (status === STATUS.ERROR) {
        $._event(status, $.message())
        $.uploader.uploadNextChunk()
      } else if (status === STATUS.SUCCESS) {
        $._event(status, $.message())
        $.tested = true
      } else if (!$.file.paused) {
        // Error might be caused by file pause method
        // Chunks does not exist on the server side
        $.tested = true
        $.send()
      }
    }
  },

  preprocessFinished: function () {
    // Compute the endByte after the preprocess function to allow an
    // implementer of preprocess to set the fileObj size
    this.endByte = this.computeEndByte()
    this.preprocessState = 2
    this.send()
  },

  readFinished: function (bytes) {
    this.readState = 2
    this.bytes = bytes
    this.send()
  },

  send: function () {
    var preprocess = this.uploader.opts.preprocess
    var read = this.uploader.opts.readFileFn
    if (utils.isFunction(preprocess)) {
      switch (this.preprocessState) {
        case 0:
          this.preprocessState = 1
          preprocess(this)
          return
        case 1:
          return
      }
    }
    switch (this.readState) {
      case 0:
        this.readState = 1
        read(this.file, this.file.fileType, this.startByte, this.endByte, this)
        return
      case 1:
        return
    }
    if (this.uploader.opts.testChunks && !this.tested) {
      this.test()
      return
    }

    this.loaded = 0
    this.total = 0
    this.pendingRetry = false

    // Set up request and listen for event
    this.xhr = new XMLHttpRequest()
    this.xhr.upload.addEventListener('progress', progressHandler, false)
    this.xhr.addEventListener('load', doneHandler, false)
    this.xhr.addEventListener('error', doneHandler, false)

    var uploadMethod = utils.evalOpts(this.uploader.opts.uploadMethod, this.file, this)
    var data = this.prepareXhrRequest(uploadMethod, false, this.uploader.opts.method, this.bytes)
    this.xhr.send(data)

    var $ = this
    function progressHandler (event) {
      if (event.lengthComputable) {
        $.loaded = event.loaded
        $.total = event.total
      }
      $._event(STATUS.PROGRESS, event)
    }

    function doneHandler (event) {
      var msg = $.message()
      $.processingResponse = true
      $.uploader.opts.processResponse(msg, function (err, res) {
        $.processingResponse = false
        if (!$.xhr) {
          return
        }
        $.processedState = {
          err: err,
          res: res
        }
        var status = $.status()
        if (status === STATUS.SUCCESS || status === STATUS.ERROR) {
          delete this.data
          $._event(status, res)
          status === STATUS.ERROR && $.uploader.uploadNextChunk()
        } else {
          $._event(STATUS.RETRY, res)
          $.pendingRetry = true
          $.abort()
          $.retries++
          var retryInterval = $.uploader.opts.chunkRetryInterval
          if (retryInterval !== null) {
            setTimeout(function () {
              $.send()
            }, retryInterval)
          } else {
            $.send()
          }
        }
      })
    }
  },

  abort: function () {
    var xhr = this.xhr
    this.xhr = null
    this.processingResponse = false
    this.processedState = null
    if (xhr) {
      xhr.abort()
    }
  },

  status: function (isTest) {
    if (this.readState === 1) {
      return STATUS.READING
    } else if (this.pendingRetry || this.preprocessState === 1) {
      // if pending retry then that's effectively the same as actively uploading,
      // there might just be a slight delay before the retry starts
      return STATUS.UPLOADING
    } else if (!this.xhr) {
      return STATUS.PENDING
    } else if (this.xhr.readyState < 4 || this.processingResponse) {
      // Status is really 'OPENED', 'HEADERS_RECEIVED'
      // or 'LOADING' - meaning that stuff is happening
      return STATUS.UPLOADING
    } else {
      var _status
      if (this.uploader.opts.successStatuses.indexOf(this.xhr.status) > -1) {
        // HTTP 200, perfect
        // HTTP 202 Accepted - The request has been accepted for processing, but the processing has not been completed.
        _status = STATUS.SUCCESS
      } else if (this.uploader.opts.permanentErrors.indexOf(this.xhr.status) > -1 ||
          !isTest && this.retries >= this.uploader.opts.maxChunkRetries) {
        // HTTP 415/500/501, permanent error
        _status = STATUS.ERROR
      } else {
        // this should never happen, but we'll reset and queue a retry
        // a likely case for this would be 503 service unavailable
        this.abort()
        _status = STATUS.PENDING
      }
      var processedState = this.processedState
      if (processedState && processedState.err) {
        _status = STATUS.ERROR
      }
      return _status
    }
  },

  message: function () {
    return this.xhr ? this.xhr.responseText : ''
  },

  progress: function () {
    if (this.pendingRetry) {
      return 0
    }
    var s = this.status()
    if (s === STATUS.SUCCESS || s === STATUS.ERROR) {
      return 1
    } else if (s === STATUS.PENDING) {
      return 0
    } else {
      return this.total > 0 ? this.loaded / this.total : 0
    }
  },

  sizeUploaded: function () {
    var size = this.endByte - this.startByte
    // can't return only chunk.loaded value, because it is bigger than chunk size
    if (this.status() !== STATUS.SUCCESS) {
      size = this.progress() * size
    }
    return size
  },

  prepareXhrRequest: function (method, isTest, paramsMethod, blob) {
    // Add data from the query options
    var query = utils.evalOpts(this.uploader.opts.query, this.file, this, isTest)
    query = utils.extend(this.getParams(), query)

    // processParams
    query = this.uploader.opts.processParams(query, this.file, this, isTest)

    var target = utils.evalOpts(this.uploader.opts.target, this.file, this, isTest)
    var data = null
    if (method === 'GET' || paramsMethod === 'octet') {
      // Add data from the query options
      var params = []
      utils.each(query, function (v, k) {
        params.push([encodeURIComponent(k), encodeURIComponent(v)].join('='))
      })
      target = this.getTarget(target, params)
      data = blob || null
    } else {
      // Add data from the query options
      data = new FormData()
      utils.each(query, function (v, k) {
        data.append(k, v)
      })
      if (typeof blob !== 'undefined') {
        data.append(this.uploader.opts.fileParameterName, blob, this.file.name)
      }
    }

    this.xhr.open(method, target, true)
    this.xhr.withCredentials = this.uploader.opts.withCredentials

    // Add data from header options
    utils.each(utils.evalOpts(this.uploader.opts.headers, this.file, this, isTest), function (v, k) {
      this.xhr.setRequestHeader(k, v)
    }, this)

    return data
  }

})

module.exports = Chunk
<commit_msg>processResponse add more params:file&chunk<commit_after>var utils = require('./utils')

function Chunk (uploader, file, offset) {
  utils.defineNonEnumerable(this, 'uploader', uploader)
  utils.defineNonEnumerable(this, 'file', file)
  utils.defineNonEnumerable(this, 'bytes', null)
  this.offset = offset
  this.tested = false
  this.retries = 0
  this.pendingRetry = false
  this.preprocessState = 0
  this.readState = 0
  this.loaded = 0
  this.total = 0
  this.chunkSize = this.uploader.opts.chunkSize
  this.startByte = this.offset * this.chunkSize
  this.endByte = this.computeEndByte()
  this.xhr = null
}

var STATUS = Chunk.STATUS = {
  PENDING: 'pending',
  UPLOADING: 'uploading',
  READING: 'reading',
  SUCCESS: 'success',
  ERROR: 'error',
  COMPLETE: 'complete',
  PROGRESS: 'progress',
  RETRY: 'retry'
}

utils.extend(Chunk.prototype, {

  _event: function (evt, args) {
    args = utils.toArray(arguments)
    args.unshift(this)
    this.file._chunkEvent.apply(this.file, args)
  },

  computeEndByte: function () {
    var endByte = Math.min(this.file.size, (this.offset + 1) * this.chunkSize)
    if (this.file.size - endByte < this.chunkSize && !this.uploader.opts.forceChunkSize) {
      // The last chunk will be bigger than the chunk size,
      // but less than 2 * this.chunkSize
      endByte = this.file.size
    }
    return endByte
  },

  getParams: function () {
    return {
      chunkNumber: this.offset + 1,
      chunkSize: this.uploader.opts.chunkSize,
      currentChunkSize: this.endByte - this.startByte,
      totalSize: this.file.size,
      identifier: this.file.uniqueIdentifier,
      filename: this.file.name,
      relativePath: this.file.relativePath,
      totalChunks: this.file.chunks.length
    }
  },

  getTarget: function (target, params) {
    if (!params.length) {
      return target
    }
    if (target.indexOf('?') < 0) {
      target += '?'
    } else {
      target += '&'
    }
    return target + params.join('&')
  },

  test: function () {
    this.xhr = new XMLHttpRequest()
    this.xhr.addEventListener('load', testHandler, false)
    this.xhr.addEventListener('error', testHandler, false)
    var testMethod = utils.evalOpts(this.uploader.opts.testMethod, this.file, this)
    var data = this.prepareXhrRequest(testMethod, true)
    this.xhr.send(data)

    var $ = this
    function testHandler (event) {
      var status = $.status(true)
      if (status === STATUS.ERROR) {
        $._event(status, $.message())
        $.uploader.uploadNextChunk()
      } else if (status === STATUS.SUCCESS) {
        $._event(status, $.message())
        $.tested = true
      } else if (!$.file.paused) {
        // Error might be caused by file pause method
        // Chunks does not exist on the server side
        $.tested = true
        $.send()
      }
    }
  },

  preprocessFinished: function () {
    // Compute the endByte after the preprocess function to allow an
    // implementer of preprocess to set the fileObj size
    this.endByte = this.computeEndByte()
    this.preprocessState = 2
    this.send()
  },

  readFinished: function (bytes) {
    this.readState = 2
    this.bytes = bytes
    this.send()
  },

  send: function () {
    var preprocess = this.uploader.opts.preprocess
    var read = this.uploader.opts.readFileFn
    if (utils.isFunction(preprocess)) {
      switch (this.preprocessState) {
        case 0:
          this.preprocessState = 1
          preprocess(this)
          return
        case 1:
          return
      }
    }
    switch (this.readState) {
      case 0:
        this.readState = 1
        read(this.file, this.file.fileType, this.startByte, this.endByte, this)
        return
      case 1:
        return
    }
    if (this.uploader.opts.testChunks && !this.tested) {
      this.test()
      return
    }

    this.loaded = 0
    this.total = 0
    this.pendingRetry = false

    // Set up request and listen for event
    this.xhr = new XMLHttpRequest()
    this.xhr.upload.addEventListener('progress', progressHandler, false)
    this.xhr.addEventListener('load', doneHandler, false)
    this.xhr.addEventListener('error', doneHandler, false)

    var uploadMethod = utils.evalOpts(this.uploader.opts.uploadMethod, this.file, this)
    var data = this.prepareXhrRequest(uploadMethod, false, this.uploader.opts.method, this.bytes)
    this.xhr.send(data)

    var $ = this
    function progressHandler (event) {
      if (event.lengthComputable) {
        $.loaded = event.loaded
        $.total = event.total
      }
      $._event(STATUS.PROGRESS, event)
    }

    function doneHandler (event) {
      var msg = $.message()
      $.processingResponse = true
      $.uploader.opts.processResponse(msg, function (err, res) {
        $.processingResponse = false
        if (!$.xhr) {
          return
        }
        $.processedState = {
          err: err,
          res: res
        }
        var status = $.status()
        if (status === STATUS.SUCCESS || status === STATUS.ERROR) {
          delete this.data
          $._event(status, res)
          status === STATUS.ERROR && $.uploader.uploadNextChunk()
        } else {
          $._event(STATUS.RETRY, res)
          $.pendingRetry = true
          $.abort()
          $.retries++
          var retryInterval = $.uploader.opts.chunkRetryInterval
          if (retryInterval !== null) {
            setTimeout(function () {
              $.send()
            }, retryInterval)
          } else {
            $.send()
          }
        }
      }, $.file, $)
    }
  },

  abort: function () {
    var xhr = this.xhr
    this.xhr = null
    this.processingResponse = false
    this.processedState = null
    if (xhr) {
      xhr.abort()
    }
  },

  status: function (isTest) {
    if (this.readState === 1) {
      return STATUS.READING
    } else if (this.pendingRetry || this.preprocessState === 1) {
      // if pending retry then that's effectively the same as actively uploading,
      // there might just be a slight delay before the retry starts
      return STATUS.UPLOADING
    } else if (!this.xhr) {
      return STATUS.PENDING
    } else if (this.xhr.readyState < 4 || this.processingResponse) {
      // Status is really 'OPENED', 'HEADERS_RECEIVED'
      // or 'LOADING' - meaning that stuff is happening
      return STATUS.UPLOADING
    } else {
      var _status
      if (this.uploader.opts.successStatuses.indexOf(this.xhr.status) > -1) {
        // HTTP 200, perfect
        // HTTP 202 Accepted - The request has been accepted for processing, but the processing has not been completed.
        _status = STATUS.SUCCESS
      } else if (this.uploader.opts.permanentErrors.indexOf(this.xhr.status) > -1 ||
          !isTest && this.retries >= this.uploader.opts.maxChunkRetries) {
        // HTTP 415/500/501, permanent error
        _status = STATUS.ERROR
      } else {
        // this should never happen, but we'll reset and queue a retry
        // a likely case for this would be 503 service unavailable
        this.abort()
        _status = STATUS.PENDING
      }
      var processedState = this.processedState
      if (processedState && processedState.err) {
        _status = STATUS.ERROR
      }
      return _status
    }
  },

  message: function () {
    return this.xhr ? this.xhr.responseText : ''
  },

  progress: function () {
    if (this.pendingRetry) {
      return 0
    }
    var s = this.status()
    if (s === STATUS.SUCCESS || s === STATUS.ERROR) {
      return 1
    } else if (s === STATUS.PENDING) {
      return 0
    } else {
      return this.total > 0 ? this.loaded / this.total : 0
    }
  },

  sizeUploaded: function () {
    var size = this.endByte - this.startByte
    // can't return only chunk.loaded value, because it is bigger than chunk size
    if (this.status() !== STATUS.SUCCESS) {
      size = this.progress() * size
    }
    return size
  },

  prepareXhrRequest: function (method, isTest, paramsMethod, blob) {
    // Add data from the query options
    var query = utils.evalOpts(this.uploader.opts.query, this.file, this, isTest)
    query = utils.extend(this.getParams(), query)

    // processParams
    query = this.uploader.opts.processParams(query, this.file, this, isTest)

    var target = utils.evalOpts(this.uploader.opts.target, this.file, this, isTest)
    var data = null
    if (method === 'GET' || paramsMethod === 'octet') {
      // Add data from the query options
      var params = []
      utils.each(query, function (v, k) {
        params.push([encodeURIComponent(k), encodeURIComponent(v)].join('='))
      })
      target = this.getTarget(target, params)
      data = blob || null
    } else {
      // Add data from the query options
      data = new FormData()
      utils.each(query, function (v, k) {
        data.append(k, v)
      })
      if (typeof blob !== 'undefined') {
        data.append(this.uploader.opts.fileParameterName, blob, this.file.name)
      }
    }

    this.xhr.open(method, target, true)
    this.xhr.withCredentials = this.uploader.opts.withCredentials

    // Add data from header options
    utils.each(utils.evalOpts(this.uploader.opts.headers, this.file, this, isTest), function (v, k) {
      this.xhr.setRequestHeader(k, v)
    }, this)

    return data
  }

})

module.exports = Chunk
<|endoftext|>


<commit_before>var assert = require('assert')
var base58check = require('bs58check')
var crypto = require('./crypto')
var enforceType = require('./types')
var networks = require('./networks')

var BigInteger = require('bigi')
var ECKey = require('./eckey')
var ECPubKey = require('./ecpubkey')

var ecurve = require('ecurve')
var curve = ecurve.getCurveByName('secp256k1')

function findBIP32ParamsByVersion(version) {
  for (var name in networks) {
    var network = networks[name]

    for (var type in network.bip32) {
      if (version != network.bip32[type]) continue

      return {
        isPrivate: (type === 'private'),
        network: network
      }
    }
  }

  assert(false, 'Could not find version ' + version.toString(16))
}

function HDNode(K, chainCode, network) {
  network = network || networks.bitcoin

  enforceType('Buffer', chainCode)

  assert.equal(chainCode.length, 32, 'Expected chainCode length of 32, got ' + chainCode.length)
  assert(network.bip32, 'Unknown BIP32 constants for network')

  this.chainCode = chainCode
  this.depth = 0
  this.index = 0
  this.network = network

  if (K instanceof BigInteger) {
    this.privKey = new ECKey(K, true)
    this.pubKey = this.privKey.pub
  } else {
    this.pubKey = new ECPubKey(K, true)
  }
}

HDNode.MASTER_SECRET = new Buffer('Bitcoin seed')
HDNode.HIGHEST_BIT = 0x80000000
HDNode.LENGTH = 78

HDNode.fromSeedBuffer = function(seed, network) {
  enforceType('Buffer', seed)

  assert(seed.length >= 16, 'Seed should be at least 128 bits')
  assert(seed.length <= 64, 'Seed should be at most 512 bits')

  var I = crypto.HmacSHA512(seed, HDNode.MASTER_SECRET)
  var IL = I.slice(0, 32)
  var IR = I.slice(32)

  // In case IL is 0 or >= n, the master key is invalid
  // This is handled by `new ECKey` in the HDNode constructor
  var pIL = BigInteger.fromBuffer(IL)

  return new HDNode(pIL, IR, network)
}

HDNode.fromSeedHex = function(hex, network) {
  return HDNode.fromSeedBuffer(new Buffer(hex, 'hex'), network)
}

HDNode.fromBase58 = function(string) {
  return HDNode.fromBuffer(base58check.decode(string), true)
}

// FIXME: remove in 2.x.y
HDNode.fromBuffer = function(buffer, __ignoreDeprecation) {
  if (!__ignoreDeprecation) {
    console.warn('HDNode.fromBuffer() is deprecated for removal in 2.x.y, use fromBase58 instead')
  }

  assert.strictEqual(buffer.length, HDNode.LENGTH, 'Invalid buffer length')

  // 4 byte: version bytes
  var version = buffer.readUInt32BE(0)
  var params = findBIP32ParamsByVersion(version)

  // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
  var depth = buffer.readUInt8(4)

  // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
  var parentFingerprint = buffer.readUInt32BE(5)
  if (depth === 0) {
    assert.strictEqual(parentFingerprint, 0x00000000, 'Invalid parent fingerprint')
  }

  // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
  // This is encoded in MSB order. (0x00000000 if master key)
  var index = buffer.readUInt32BE(9)
  assert(depth > 0 || index === 0, 'Invalid index')

  // 32 bytes: the chain code
  var chainCode = buffer.slice(13, 45)
  var data, hd

  // 33 bytes: private key data (0x00 + k)
  if (params.isPrivate) {
    assert.strictEqual(buffer.readUInt8(45), 0x00, 'Invalid private key')
    data = buffer.slice(46, 78)
    var d = BigInteger.fromBuffer(data)
    hd = new HDNode(d, chainCode, params.network)

  // 33 bytes: public key data (0x02 + X or 0x03 + X)
  } else {
    data = buffer.slice(45, 78)
    var Q = ecurve.Point.decodeFrom(curve, data)
    assert.equal(Q.compressed, true, 'Invalid public key')

    // Verify that the X coordinate in the public point corresponds to a point on the curve.
    // If not, the extended public key is invalid.
    curve.validate(Q)

    hd = new HDNode(Q, chainCode, params.network)
  }

  hd.depth = depth
  hd.index = index
  hd.parentFingerprint = parentFingerprint

  return hd
}

// FIXME: remove in 2.x.y
HDNode.fromHex = function(hex) {
  return HDNode.fromBuffer(new Buffer(hex, 'hex'))
}

HDNode.prototype.getIdentifier = function() {
  return crypto.hash160(this.pubKey.toBuffer())
}

HDNode.prototype.getFingerprint = function() {
  return this.getIdentifier().slice(0, 4)
}

HDNode.prototype.getAddress = function() {
  return this.pubKey.getAddress(this.network)
}

HDNode.prototype.neutered = function() {
  var neutered = new HDNode(this.pubKey.Q, this.chainCode, this.network)
  neutered.depth = this.depth
  neutered.index = this.index
  neutered.parentFingerprint = this.parentFingerprint

  return neutered
}

HDNode.prototype.toBase58 = function(isPrivate) {
  return base58check.encode(this.toBuffer(isPrivate, true))
}

// FIXME: remove in 2.x.y
HDNode.prototype.toBuffer = function(isPrivate, __ignoreDeprecation) {
  if (isPrivate === undefined) {
    isPrivate = !!this.privKey

  // FIXME: remove in 2.x.y
  } else {
    console.warn('isPrivate flag is deprecated, please use the .neutered() method instead')
  }

  if (!__ignoreDeprecation) {
    console.warn('HDNode.toBuffer() is deprecated for removal in 2.x.y, use toBase58 instead')
  }

  // Version
  var version = isPrivate ? this.network.bip32.private : this.network.bip32.public
  var buffer = new Buffer(HDNode.LENGTH)

  // 4 bytes: version bytes
  buffer.writeUInt32BE(version, 0)

  // Depth
  // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
  buffer.writeUInt8(this.depth, 4)

  // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
  var fingerprint = (this.depth === 0) ? 0x00000000 : this.parentFingerprint
  buffer.writeUInt32BE(fingerprint, 5)

  // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
  // This is encoded in Big endian. (0x00000000 if master key)
  buffer.writeUInt32BE(this.index, 9)

  // 32 bytes: the chain code
  this.chainCode.copy(buffer, 13)

  // 33 bytes: the public key or private key data
  if (isPrivate) {
    // FIXME: remove in 2.x.y
    assert(this.privKey, 'Missing private key')

    // 0x00 + k for private keys
    buffer.writeUInt8(0, 45)
    this.privKey.d.toBuffer(32).copy(buffer, 46)
  } else {

    // X9.62 encoding for public keys
    this.pubKey.toBuffer().copy(buffer, 45)
  }

  return buffer
}

// FIXME: remove in 2.x.y
HDNode.prototype.toHex = function(isPrivate) {
  return this.toBuffer(isPrivate).toString('hex')
}

// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
HDNode.prototype.derive = function(index) {
  var isHardened = index >= HDNode.HIGHEST_BIT
  var indexBuffer = new Buffer(4)
  indexBuffer.writeUInt32BE(index, 0)

  var data

  // Hardened child
  if (isHardened) {
    assert(this.privKey, 'Could not derive hardened child key')

    // data = 0x00 || ser256(kpar) || ser32(index)
    data = Buffer.concat([
      this.privKey.d.toBuffer(33),
      indexBuffer
    ])

  // Normal child
  } else {
    // data = serP(point(kpar)) || ser32(index)
    //      = serP(Kpar) || ser32(index)
    data = Buffer.concat([
      this.pubKey.toBuffer(),
      indexBuffer
    ])
  }

  var I = crypto.HmacSHA512(data, this.chainCode)
  var IL = I.slice(0, 32)
  var IR = I.slice(32)

  var pIL = BigInteger.fromBuffer(IL)

  // In case parse256(IL) >= n, proceed with the next value for i
  if (pIL.compareTo(curve.n) >= 0) {
    return this.derive(index + 1)
  }

  // Private parent key -> private child key
  var hd
  if (this.privKey) {
    // ki = parse256(IL) + kpar (mod n)
    var ki = pIL.add(this.privKey.d).mod(curve.n)

    // In case ki == 0, proceed with the next value for i
    if (ki.signum() === 0) {
      return this.derive(index + 1)
    }

    hd = new HDNode(ki, IR, this.network)

  // Public parent key -> public child key
  } else {
    // Ki = point(parse256(IL)) + Kpar
    //    = G*IL + Kpar
    var Ki = curve.G.multiply(pIL).add(this.pubKey.Q)

    // In case Ki is the point at infinity, proceed with the next value for i
    if (curve.isInfinity(Ki)) {
      return this.derive(index + 1)
    }

    hd = new HDNode(Ki, IR, this.network)
  }

  hd.depth = this.depth + 1
  hd.index = index
  hd.parentFingerprint = this.getFingerprint().readUInt32BE(0)

  return hd
}

HDNode.prototype.deriveHardened = function(index) {
  // Only derives hardened private keys by default
  return this.derive(index + HDNode.HIGHEST_BIT)
}

HDNode.prototype.toString = HDNode.prototype.toBase58

module.exports = HDNode
<commit_msg>HDNode: avoid walking bip32 object<commit_after>var assert = require('assert')
var base58check = require('bs58check')
var crypto = require('./crypto')
var enforceType = require('./types')
var networks = require('./networks')

var BigInteger = require('bigi')
var ECKey = require('./eckey')
var ECPubKey = require('./ecpubkey')

var ecurve = require('ecurve')
var curve = ecurve.getCurveByName('secp256k1')

function findBIP32ParamsByVersion(version) {
  for (var name in networks) {
    var network = networks[name]

    if (version === network.bip32.private ||
        version === network.bip32.public) {

      return {
        isPrivate: (version === network.bip32.private),
        network: network
      }
    }
  }

  assert(false, 'Could not find version ' + version.toString(16))
}

function HDNode(K, chainCode, network) {
  network = network || networks.bitcoin

  enforceType('Buffer', chainCode)

  assert.equal(chainCode.length, 32, 'Expected chainCode length of 32, got ' + chainCode.length)
  assert(network.bip32, 'Unknown BIP32 constants for network')

  this.chainCode = chainCode
  this.depth = 0
  this.index = 0
  this.network = network

  if (K instanceof BigInteger) {
    this.privKey = new ECKey(K, true)
    this.pubKey = this.privKey.pub
  } else {
    this.pubKey = new ECPubKey(K, true)
  }
}

HDNode.MASTER_SECRET = new Buffer('Bitcoin seed')
HDNode.HIGHEST_BIT = 0x80000000
HDNode.LENGTH = 78

HDNode.fromSeedBuffer = function(seed, network) {
  enforceType('Buffer', seed)

  assert(seed.length >= 16, 'Seed should be at least 128 bits')
  assert(seed.length <= 64, 'Seed should be at most 512 bits')

  var I = crypto.HmacSHA512(seed, HDNode.MASTER_SECRET)
  var IL = I.slice(0, 32)
  var IR = I.slice(32)

  // In case IL is 0 or >= n, the master key is invalid
  // This is handled by `new ECKey` in the HDNode constructor
  var pIL = BigInteger.fromBuffer(IL)

  return new HDNode(pIL, IR, network)
}

HDNode.fromSeedHex = function(hex, network) {
  return HDNode.fromSeedBuffer(new Buffer(hex, 'hex'), network)
}

HDNode.fromBase58 = function(string) {
  return HDNode.fromBuffer(base58check.decode(string), true)
}

// FIXME: remove in 2.x.y
HDNode.fromBuffer = function(buffer, __ignoreDeprecation) {
  if (!__ignoreDeprecation) {
    console.warn('HDNode.fromBuffer() is deprecated for removal in 2.x.y, use fromBase58 instead')
  }

  assert.strictEqual(buffer.length, HDNode.LENGTH, 'Invalid buffer length')

  // 4 byte: version bytes
  var version = buffer.readUInt32BE(0)
  var params = findBIP32ParamsByVersion(version)

  // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ...
  var depth = buffer.readUInt8(4)

  // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
  var parentFingerprint = buffer.readUInt32BE(5)
  if (depth === 0) {
    assert.strictEqual(parentFingerprint, 0x00000000, 'Invalid parent fingerprint')
  }

  // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
  // This is encoded in MSB order. (0x00000000 if master key)
  var index = buffer.readUInt32BE(9)
  assert(depth > 0 || index === 0, 'Invalid index')

  // 32 bytes: the chain code
  var chainCode = buffer.slice(13, 45)
  var data, hd

  // 33 bytes: private key data (0x00 + k)
  if (params.isPrivate) {
    assert.strictEqual(buffer.readUInt8(45), 0x00, 'Invalid private key')
    data = buffer.slice(46, 78)
    var d = BigInteger.fromBuffer(data)
    hd = new HDNode(d, chainCode, params.network)

  // 33 bytes: public key data (0x02 + X or 0x03 + X)
  } else {
    data = buffer.slice(45, 78)
    var Q = ecurve.Point.decodeFrom(curve, data)
    assert.equal(Q.compressed, true, 'Invalid public key')

    // Verify that the X coordinate in the public point corresponds to a point on the curve.
    // If not, the extended public key is invalid.
    curve.validate(Q)

    hd = new HDNode(Q, chainCode, params.network)
  }

  hd.depth = depth
  hd.index = index
  hd.parentFingerprint = parentFingerprint

  return hd
}

// FIXME: remove in 2.x.y
HDNode.fromHex = function(hex) {
  return HDNode.fromBuffer(new Buffer(hex, 'hex'))
}

HDNode.prototype.getIdentifier = function() {
  return crypto.hash160(this.pubKey.toBuffer())
}

HDNode.prototype.getFingerprint = function() {
  return this.getIdentifier().slice(0, 4)
}

HDNode.prototype.getAddress = function() {
  return this.pubKey.getAddress(this.network)
}

HDNode.prototype.neutered = function() {
  var neutered = new HDNode(this.pubKey.Q, this.chainCode, this.network)
  neutered.depth = this.depth
  neutered.index = this.index
  neutered.parentFingerprint = this.parentFingerprint

  return neutered
}

HDNode.prototype.toBase58 = function(isPrivate) {
  return base58check.encode(this.toBuffer(isPrivate, true))
}

// FIXME: remove in 2.x.y
HDNode.prototype.toBuffer = function(isPrivate, __ignoreDeprecation) {
  if (isPrivate === undefined) {
    isPrivate = !!this.privKey

  // FIXME: remove in 2.x.y
  } else {
    console.warn('isPrivate flag is deprecated, please use the .neutered() method instead')
  }

  if (!__ignoreDeprecation) {
    console.warn('HDNode.toBuffer() is deprecated for removal in 2.x.y, use toBase58 instead')
  }

  // Version
  var version = isPrivate ? this.network.bip32.private : this.network.bip32.public
  var buffer = new Buffer(HDNode.LENGTH)

  // 4 bytes: version bytes
  buffer.writeUInt32BE(version, 0)

  // Depth
  // 1 byte: depth: 0x00 for master nodes, 0x01 for level-1 descendants, ....
  buffer.writeUInt8(this.depth, 4)

  // 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
  var fingerprint = (this.depth === 0) ? 0x00000000 : this.parentFingerprint
  buffer.writeUInt32BE(fingerprint, 5)

  // 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
  // This is encoded in Big endian. (0x00000000 if master key)
  buffer.writeUInt32BE(this.index, 9)

  // 32 bytes: the chain code
  this.chainCode.copy(buffer, 13)

  // 33 bytes: the public key or private key data
  if (isPrivate) {
    // FIXME: remove in 2.x.y
    assert(this.privKey, 'Missing private key')

    // 0x00 + k for private keys
    buffer.writeUInt8(0, 45)
    this.privKey.d.toBuffer(32).copy(buffer, 46)
  } else {

    // X9.62 encoding for public keys
    this.pubKey.toBuffer().copy(buffer, 45)
  }

  return buffer
}

// FIXME: remove in 2.x.y
HDNode.prototype.toHex = function(isPrivate) {
  return this.toBuffer(isPrivate).toString('hex')
}

// https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#child-key-derivation-ckd-functions
HDNode.prototype.derive = function(index) {
  var isHardened = index >= HDNode.HIGHEST_BIT
  var indexBuffer = new Buffer(4)
  indexBuffer.writeUInt32BE(index, 0)

  var data

  // Hardened child
  if (isHardened) {
    assert(this.privKey, 'Could not derive hardened child key')

    // data = 0x00 || ser256(kpar) || ser32(index)
    data = Buffer.concat([
      this.privKey.d.toBuffer(33),
      indexBuffer
    ])

  // Normal child
  } else {
    // data = serP(point(kpar)) || ser32(index)
    //      = serP(Kpar) || ser32(index)
    data = Buffer.concat([
      this.pubKey.toBuffer(),
      indexBuffer
    ])
  }

  var I = crypto.HmacSHA512(data, this.chainCode)
  var IL = I.slice(0, 32)
  var IR = I.slice(32)

  var pIL = BigInteger.fromBuffer(IL)

  // In case parse256(IL) >= n, proceed with the next value for i
  if (pIL.compareTo(curve.n) >= 0) {
    return this.derive(index + 1)
  }

  // Private parent key -> private child key
  var hd
  if (this.privKey) {
    // ki = parse256(IL) + kpar (mod n)
    var ki = pIL.add(this.privKey.d).mod(curve.n)

    // In case ki == 0, proceed with the next value for i
    if (ki.signum() === 0) {
      return this.derive(index + 1)
    }

    hd = new HDNode(ki, IR, this.network)

  // Public parent key -> public child key
  } else {
    // Ki = point(parse256(IL)) + Kpar
    //    = G*IL + Kpar
    var Ki = curve.G.multiply(pIL).add(this.pubKey.Q)

    // In case Ki is the point at infinity, proceed with the next value for i
    if (curve.isInfinity(Ki)) {
      return this.derive(index + 1)
    }

    hd = new HDNode(Ki, IR, this.network)
  }

  hd.depth = this.depth + 1
  hd.index = index
  hd.parentFingerprint = this.getFingerprint().readUInt32BE(0)

  return hd
}

HDNode.prototype.deriveHardened = function(index) {
  // Only derives hardened private keys by default
  return this.derive(index + HDNode.HIGHEST_BIT)
}

HDNode.prototype.toString = HDNode.prototype.toBase58

module.exports = HDNode
<|endoftext|>


<commit_before>import deline from 'deline';
import invariant from 'invariant';
import { KEY, LIFECYCLE } from './constants';

const VALID_KEYS = {
  start: true,
  success: true,
  failure: true,
  finish: true,
  always: true,
};

function verifyHandlers(handlers, action) {
  Object.keys(handlers).forEach(key => {
    invariant(VALID_KEYS[key], deline`
      The handler for action ${action.type} had a ${key} property defined, but this is not
      a valid key for a redux-pack handler. Valid keys are: ${Object.keys(VALID_KEYS)}
    `);
  });
}

function safeMap(state, fn, action, name) {
  switch (typeof fn) {
    case 'function': {
      const result = fn(state);
      invariant(result !== undefined, deline`
        The ${name} handler for action ${action.type} is expected to return a new state object.
      `);
      return result;
    }
    case 'undefined':
      return state;
    default:
      // if we've dropped into this case, we've got a problem. Someone is setting
      // things on the handler object they aren't supposed to.
      invariant(false, deline`
        The ${name} handler for action ${action.type} is expected to be a function,
        but found ${typeof fn} instead.
      `);
      return state;
  }
}

function handle(startingState, action, handlers) {
  if (process.env.NODE_ENV === 'development') {
    verifyHandlers(handlers, action);
  }
  const { meta } = action;
  const lifecycle = meta ? meta[KEY.LIFECYCLE] : null;

  if (lifecycle == null) {
    invariant(false, deline`
      You used redux-pack's \`handle(...)\` function on the action ${action.type}, however, it
      doesn't appear to be an action that was dispatched by redux-pack. This is likely an error.
    `);
    return startingState;
  }

  let state = startingState;
  switch (lifecycle) {
    case LIFECYCLE.START:
      state = safeMap(state, handlers.start, action, 'start');
      break;
    case LIFECYCLE.SUCCESS:
      state = safeMap(state, handlers.success, action, 'success');
      state = safeMap(state, handlers.finish, action, 'finish');
      break;
    case LIFECYCLE.FAILURE:
      state = safeMap(state, handlers.failure, action, 'failure');
      state = safeMap(state, handlers.finish, action, 'finish');
      break;
    default:
      // do nothing
      break;
  }
  state = safeMap(state, handlers.always, action, 'always');
  return state;
}

module.exports = handle;
<commit_msg>Provide action object as second parameter of handle handlers<commit_after>import deline from 'deline';
import invariant from 'invariant';
import { KEY, LIFECYCLE } from './constants';

const VALID_KEYS = {
  start: true,
  success: true,
  failure: true,
  finish: true,
  always: true,
};

function verifyHandlers(handlers, action) {
  Object.keys(handlers).forEach(key => {
    invariant(VALID_KEYS[key], deline`
      The handler for action ${action.type} had a ${key} property defined, but this is not
      a valid key for a redux-pack handler. Valid keys are: ${Object.keys(VALID_KEYS)}
    `);
  });
}

function safeMap(state, fn, action, name) {
  switch (typeof fn) {
    case 'function': {
      const result = fn(state, action);
      invariant(result !== undefined, deline`
        The ${name} handler for action ${action.type} is expected to return a new state object.
      `);
      return result;
    }
    case 'undefined':
      return state;
    default:
      // if we've dropped into this case, we've got a problem. Someone is setting
      // things on the handler object they aren't supposed to.
      invariant(false, deline`
        The ${name} handler for action ${action.type} is expected to be a function,
        but found ${typeof fn} instead.
      `);
      return state;
  }
}

function handle(startingState, action, handlers) {
  if (process.env.NODE_ENV === 'development') {
    verifyHandlers(handlers, action);
  }
  const { meta } = action;
  const lifecycle = meta ? meta[KEY.LIFECYCLE] : null;

  if (lifecycle == null) {
    invariant(false, deline`
      You used redux-pack's \`handle(...)\` function on the action ${action.type}, however, it
      doesn't appear to be an action that was dispatched by redux-pack. This is likely an error.
    `);
    return startingState;
  }

  let state = startingState;
  switch (lifecycle) {
    case LIFECYCLE.START:
      state = safeMap(state, handlers.start, action, 'start');
      break;
    case LIFECYCLE.SUCCESS:
      state = safeMap(state, handlers.success, action, 'success');
      state = safeMap(state, handlers.finish, action, 'finish');
      break;
    case LIFECYCLE.FAILURE:
      state = safeMap(state, handlers.failure, action, 'failure');
      state = safeMap(state, handlers.finish, action, 'finish');
      break;
    default:
      // do nothing
      break;
  }
  state = safeMap(state, handlers.always, action, 'always');
  return state;
}

module.exports = handle;
<|endoftext|>


<commit_before>const CONSTANTS = require('./constants');

/**
 * Remove unnecessary strings in the details
 * @param {string} detail
 * @returns {string}
 */
const cleanUpDetails = detail => {
	const stringsToRemove = new Set(['exgym ', 'ex gym ', 'shiny check ', 'shinycheck ', 'rarecandy ', 'candy ', 'silverpinap ', 'silver pinap', 'pinap ', 'technical ', 'technicalmachine ', 'technical machine ', 'finalevo ', 'highiv ']);
	stringsToRemove.forEach(string => {
		const regex = new RegExp(string, 'gi');
		detail = detail.replace(regex, '');
	});
	if (detail.length > 255) detail = detail.substring(0,255);
	return detail;
};

/**
 * Format a date object as a string in 12 hour format
 * @param {object} dateObj
 * @returns {string}
 */
const formatTime = dateObj => {
	let hour = dateObj.getHours();
	let minute = dateObj.getMinutes();
	const amPM = hour > 11 ? 'pm' : 'am';
	if (hour > 12) {
		hour -= 12;
	} else if (hour === 0) {
		hour = '12';
	}
	if (minute < 10) minute = `0${minute}`;
	return `${hour}:${minute}${amPM}`;
};

/**
 * Returns end time of egg/raid
 * @param {number} minutesLeft
 * @returns {string}
 */
const getEndTime = minutesLeft => {
	const date = new Date();
	date.setMinutes(date.getMinutes() + minutesLeft);
	return formatTime(date);
};

/**
 * Checks if legendary and returns @legendary tag
 * @param {string} boss
 * @param {array} legendaries
 * @param {object} data
 * @returns {string}
 */
const getLegendaryTag = (boss, legendaries, data) => {
	if (legendaries.includes(boss)) {
		if (data.rolesByName['legendary']) {
			return '<@&' + data.rolesByName['legendary'].id + '> ';
		} else {
			console.warn('Please create a role called legendary.');
		}
	}
	return '';
};

/**
 * If the Pokemon name is found as a role, put in mention format
 * @param {string} pokemonName
 * @param {object} data
 * @returns {string}
 */
const getPokemonTag = (pokemonName, data) => {
	let pokemonTag = pokemonName;
	data.GUILD.roles.forEach(role => {
		if (role.name === pokemonName) pokemonTag = '<@&' + role.id + '>';
	});
	return pokemonTag;
};

/**
 * Checks what reward was reported and returns reward and reward tag
 * @param {string} msgLower
 * @param {object} data
 * @returns {string}
 */
const getRewardAndRewardTag = (reward, msgLower, data) => {
	const technicalMachineVariations = new Set(['chargetm', 'chargedtm', 'charged_tm', 'fast_tm', 'fasttm', 'tm', 'charge', 'charged', 'fast']);
	const rareCandyVariations = new Set(['rc', 'rarecand', 'rarecandy', 'rare_candy', 'rare', 'cand', 'candy']);
	const stardustVariations = new Set(['stardust', 'dust']);
	const silverPinapVariations = new Set(['silverpinap', 'silver']);

	if (rareCandyVariations.has(reward)) {
		reward = 'rarecandy';
	} else if (technicalMachineVariations.has(reward)) {
		reward = 'technical_machine';
	} else if (stardustVariations.has(reward)) {
		reward = 'stardust';
	} else if (silverPinapVariations.has(reward)) {
		reward = 'silver_pinap';
	}

	let rewardTag = reward;

	// If the reward name is found as a role, put in mention format
	data.GUILD.roles.forEach(role => {
		if (role.name === reward) rewardTag = '<@&' + role.id + '>';
	});

	// Check to see if the message contains a mention of 'shiny'
	data.GUILD.roles.forEach(role => {
		if (msgLower.includes('shiny') && role.name === 'shinycheck') rewardTag += ' <@&' + role.id + '> ' + data.getEmoji('shiny');
	});

	return { reward, rewardTag };
};

/**
 * If the Pokemon exists, return shadow mention tag
 * @param {string} pokemonName
 * @param {string} message
 * @param {object} data
 * @returns {string}
 */
const getShadowTag = (pokemonName, message, data) => {
	let shadowTag = '';
	if (message.content.includes(pokemonName) && data.rolesByName['shadow']) {
		shadowTag = ' <@&' + data.rolesByName['shadow'].id + '> ';
	}
	return shadowTag;
};

/**
 * Checks if exgym and returns @exgym tag
 * @param {string} msgLower
 * @param {object} data
 * @returns {string}
 */
const getSpecialRaidTag = (msglower, data) => {
	if (msglower.includes('exgym') || msglower.includes(' ex gym') || msglower.includes('ex raid') || msglower.includes('(ex gym)')) {
		if (data.rolesByName['exgym']) {
			return '<@&' + data.rolesByName['exgym'].id + '> ';
		} else {
			console.warn('Please create a role called exgym.');
		}
	}
	return '';
};

/**
 * Checks if message has special wild tag and returns appropriate mention tag
 * @param {string} msgLower
 * @param {object} data
 * @returns {string}
 */
const getSpecialWildTag = (msgLower, data) => {
	let specialWildTag = '';

	// Tags role called highiv whenever 'highiv' is in a report
	if (msgLower.includes('highiv')) {
		data.GUILD.roles.forEach(role => {
			if (role.name === 'highiv') specialWildTag += ' <@&' + role.id + '> '; // require a role called 'highiv'
		});
	}
	// Tags role called shinycheck whenever 'shiny' is in a report
	if (msgLower.includes('shiny')) {
		data.GUILD.roles.forEach(role => {
			if (role.name === 'shinycheck') specialWildTag += ' <@&' + role.id + '> ' + data.getEmoji('shiny'); // require a role called 'shinycheck'
		});
	}
	// Tags role called shinycheck whenever 'finalevo' is in a report
	if (msgLower.includes('finalevo')) {
		data.GUILD.roles.forEach(role => {
			if (role.name === 'finalevo') specialWildTag += ' <@&' + role.id + '> '; // require a role called 'finalevo'
		});
	}

	return specialWildTag;
};

/**
 * Checks raid type and tier then returns tier emoji and egg tag
 * @param {number} tier
 * @param {object} data
 * @returns {object}
 */
const getTierEmojiAndEggTag = (tier, data) => {
	let tierEmoji = '';
	let eggTag = 'Tier ' + tier;
	if (tier == 5) {
		tierEmoji = 'legendaryraid';
		eggTag = ' <@&' + data.rolesByName['tier5'].id + '> ';
	} else if (tier < 3) {
		tierEmoji = 'normalraid';
		if(tier == 1) eggTag = ' <@&' + data.rolesByName['tier1'].id + '> ';
		if(tier == 2) eggTag = ' <@&' + data.rolesByName['tier2'].id + '> ';
	} else if (tier > 2) {
		tierEmoji = 'rareraid';
		if(tier == 3) eggTag = ' <@&' + data.rolesByName['tier3'].id + '> ';
		if(tier == 4) eggTag = ' <@&' + data.rolesByName['tier4'].id + '> ';
	}
	return { tierEmoji, eggTag };
};

/**
 * Removes tags for html
 * @param {string} html
 * @returns {string}
 */
const removeTags = html => {
	let oldHtml;
	do {
		oldHtml = html;
		html = html.replace(CONSTANTS.tagOrComment, '');
	} while (html !== oldHtml);
	return html.replace(/</g, '<');
};

/**
 * Sends alert to channel if it exists
 * @param {string} channelName
 * @param {string} reply
 * @param {object} data
 */
const sendAlertToChannel = (channelName, reply, data) => {
	if (data.channelsByName[channelName]) {
		data.channelsByName[channelName].send(reply);
	} else {
		console.warn(`Please add a channel called #${channelName}.`);
	}
};

module.exports = {
	cleanUpDetails,
	formatTime,
	getEndTime,
	getLegendaryTag,
	getPokemonTag,
	getRewardAndRewardTag,
	getShadowTag,
	getSpecialRaidTag,
	getSpecialWildTag,
	getTierEmojiAndEggTag,
	removeTags,
	sendAlertToChannel
};
<commit_msg>Added a few more variations to stringsToRemove<commit_after>const CONSTANTS = require('./constants');

/**
 * Remove unnecessary strings in the details
 * @param {string} detail
 * @returns {string}
 */
const cleanUpDetails = detail => {
	const exGymVariations = ['exgym ', 'ex gym ', 'ex raid ', '(exgym) ', '(ex gym) '];
	const shinyCheckVariations = ['shiny check ', 'shinycheck '];
	const rareCandyVariations = ['rarecandy ', 'candy '];
	const silverPinapVariations = ['silverpinap ', 'silver pinap', 'pinap '];
	const technicalMachineVariations = ['technical ', 'technicalmachine ', 'technical machine '];
	const stringsToRemove = new Set([
		...exGymVariations,
		...shinyCheckVariations,
		...rareCandyVariations,
		...silverPinapVariations,
		...technicalMachineVariations,
		'finalevo ',
		'highiv '
		]);

	stringsToRemove.forEach(string => {
		const regex = new RegExp(string, 'gi');
		detail = detail.replace(regex, '');
	});
	if (detail.length > 255) detail = detail.substring(0,255);
	return detail;
};

/**
 * Format a date object as a string in 12 hour format
 * @param {object} dateObj
 * @returns {string}
 */
const formatTime = dateObj => {
	let hour = dateObj.getHours();
	let minute = dateObj.getMinutes();
	const amPM = hour > 11 ? 'pm' : 'am';
	if (hour > 12) {
		hour -= 12;
	} else if (hour === 0) {
		hour = '12';
	}
	if (minute < 10) minute = `0${minute}`;
	return `${hour}:${minute}${amPM}`;
};

/**
 * Returns end time of egg/raid
 * @param {number} minutesLeft
 * @returns {string}
 */
const getEndTime = minutesLeft => {
	const date = new Date();
	date.setMinutes(date.getMinutes() + minutesLeft);
	return formatTime(date);
};

/**
 * Checks if legendary and returns @legendary tag
 * @param {string} boss
 * @param {array} legendaries
 * @param {object} data
 * @returns {string}
 */
const getLegendaryTag = (boss, legendaries, data) => {
	if (legendaries.includes(boss)) {
		if (data.rolesByName['legendary']) {
			return '<@&' + data.rolesByName['legendary'].id + '> ';
		} else {
			console.warn('Please create a role called legendary.');
		}
	}
	return '';
};

/**
 * If the Pokemon name is found as a role, put in mention format
 * @param {string} pokemonName
 * @param {object} data
 * @returns {string}
 */
const getPokemonTag = (pokemonName, data) => {
	let pokemonTag = pokemonName;
	data.GUILD.roles.forEach(role => {
		if (role.name === pokemonName) pokemonTag = '<@&' + role.id + '>';
	});
	return pokemonTag;
};

/**
 * Checks what reward was reported and returns reward and reward tag
 * @param {string} msgLower
 * @param {object} data
 * @returns {string}
 */
const getRewardAndRewardTag = (reward, msgLower, data) => {
	const technicalMachineVariations = new Set(['chargetm', 'chargedtm', 'charged_tm', 'fast_tm', 'fasttm', 'tm', 'charge', 'charged', 'fast']);
	const rareCandyVariations = new Set(['rc', 'rarecand', 'rarecandy', 'rare_candy', 'rare', 'cand', 'candy']);
	const stardustVariations = new Set(['stardust', 'dust']);
	const silverPinapVariations = new Set(['silverpinap', 'silver']);

	if (rareCandyVariations.has(reward)) {
		reward = 'rarecandy';
	} else if (technicalMachineVariations.has(reward)) {
		reward = 'technical_machine';
	} else if (stardustVariations.has(reward)) {
		reward = 'stardust';
	} else if (silverPinapVariations.has(reward)) {
		reward = 'silver_pinap';
	}

	let rewardTag = reward;

	// If the reward name is found as a role, put in mention format
	data.GUILD.roles.forEach(role => {
		if (role.name === reward) rewardTag = '<@&' + role.id + '>';
	});

	// Check to see if the message contains a mention of 'shiny'
	data.GUILD.roles.forEach(role => {
		if (msgLower.includes('shiny') && role.name === 'shinycheck') rewardTag += ' <@&' + role.id + '> ' + data.getEmoji('shiny');
	});

	return { reward, rewardTag };
};

/**
 * If the Pokemon exists, return shadow mention tag
 * @param {string} pokemonName
 * @param {string} message
 * @param {object} data
 * @returns {string}
 */
const getShadowTag = (pokemonName, message, data) => {
	let shadowTag = '';
	if (message.content.includes(pokemonName) && data.rolesByName['shadow']) {
		shadowTag = ' <@&' + data.rolesByName['shadow'].id + '> ';
	}
	return shadowTag;
};

/**
 * Checks if exgym and returns @exgym tag
 * @param {string} msgLower
 * @param {object} data
 * @returns {string}
 */
const getSpecialRaidTag = (msglower, data) => {
	if (msglower.includes('exgym') || msglower.includes(' ex gym') || msglower.includes('ex raid') || msglower.includes('(ex gym)')) {
		if (data.rolesByName['exgym']) {
			return '<@&' + data.rolesByName['exgym'].id + '> ';
		} else {
			console.warn('Please create a role called exgym.');
		}
	}
	return '';
};

/**
 * Checks if message has special wild tag and returns appropriate mention tag
 * @param {string} msgLower
 * @param {object} data
 * @returns {string}
 */
const getSpecialWildTag = (msgLower, data) => {
	let specialWildTag = '';

	// Tags role called highiv whenever 'highiv' is in a report
	if (msgLower.includes('highiv')) {
		data.GUILD.roles.forEach(role => {
			if (role.name === 'highiv') specialWildTag += ' <@&' + role.id + '> '; // require a role called 'highiv'
		});
	}
	// Tags role called shinycheck whenever 'shiny' is in a report
	if (msgLower.includes('shiny')) {
		data.GUILD.roles.forEach(role => {
			if (role.name === 'shinycheck') specialWildTag += ' <@&' + role.id + '> ' + data.getEmoji('shiny'); // require a role called 'shinycheck'
		});
	}
	// Tags role called shinycheck whenever 'finalevo' is in a report
	if (msgLower.includes('finalevo')) {
		data.GUILD.roles.forEach(role => {
			if (role.name === 'finalevo') specialWildTag += ' <@&' + role.id + '> '; // require a role called 'finalevo'
		});
	}

	return specialWildTag;
};

/**
 * Checks raid type and tier then returns tier emoji and egg tag
 * @param {number} tier
 * @param {object} data
 * @returns {object}
 */
const getTierEmojiAndEggTag = (tier, data) => {
	let tierEmoji = '';
	let eggTag = 'Tier ' + tier;
	if (tier == 5) {
		tierEmoji = 'legendaryraid';
		eggTag = ' <@&' + data.rolesByName['tier5'].id + '> ';
	} else if (tier < 3) {
		tierEmoji = 'normalraid';
		if(tier == 1) eggTag = ' <@&' + data.rolesByName['tier1'].id + '> ';
		if(tier == 2) eggTag = ' <@&' + data.rolesByName['tier2'].id + '> ';
	} else if (tier > 2) {
		tierEmoji = 'rareraid';
		if(tier == 3) eggTag = ' <@&' + data.rolesByName['tier3'].id + '> ';
		if(tier == 4) eggTag = ' <@&' + data.rolesByName['tier4'].id + '> ';
	}
	return { tierEmoji, eggTag };
};

/**
 * Removes tags for html
 * @param {string} html
 * @returns {string}
 */
const removeTags = html => {
	let oldHtml;
	do {
		oldHtml = html;
		html = html.replace(CONSTANTS.tagOrComment, '');
	} while (html !== oldHtml);
	return html.replace(/</g, '<');
};

/**
 * Sends alert to channel if it exists
 * @param {string} channelName
 * @param {string} reply
 * @param {object} data
 */
const sendAlertToChannel = (channelName, reply, data) => {
	if (data.channelsByName[channelName]) {
		data.channelsByName[channelName].send(reply);
	} else {
		console.warn(`Please add a channel called #${channelName}.`);
	}
};

module.exports = {
	cleanUpDetails,
	formatTime,
	getEndTime,
	getLegendaryTag,
	getPokemonTag,
	getRewardAndRewardTag,
	getShadowTag,
	getSpecialRaidTag,
	getSpecialWildTag,
	getTierEmojiAndEggTag,
	removeTags,
	sendAlertToChannel
};
<|endoftext|>