<commit_before>const ERR = require('async-stacktrace');
const fs = require('fs-extra');
const async = require('async');
const tmp = require('tmp');
const Docker = require('dockerode');
const AWS = require('aws-sdk');
const { exec } = require('child_process');
const path = require('path');
const fetch = require('node-fetch');
const byline = require('byline');

const globalLogger = require('./lib/logger');
const config = require('./lib/config');
const queueReceiver = require('./lib/queueReceiver');
const util = require('./lib/util');

async.series([
    (callback) => {
        config.loadConfig((err) => {
            if (ERR(err, callback)) {
                globalLogger.error('Failed to load config; exiting process');
                process.exit(1);
            }
            callback(null);
        });
    },
    () => {
        globalLogger.info('Initialization complete; beginning to process jobs');
        queueReceiver(config.queueUrl, (message, logger, fail, success) => {
            handleMessage(message, logger, (err) => {
                if (ERR(err, fail)) return;
                success();
            });
        });
    }
]);

function handleMessage(messageBody, logger, done) {
    logger.info(`Grading job ${messageBody.jobId}!`);
    logger.info(messageBody);

    async.auto({
        context: function(callback) {
            logger.info('Creating context for job execution');
            const context = {
                docker: new Docker(),
                s3: new AWS.S3(),
                logger: logger,
                startTime: new Date().toISOString(),
                job: {
                    ...messageBody
                }
            };
            callback(null, context);
        },
        initDocker: ['context', initDocker],
        initFiles: ['context', initFiles],
        runJob: ['initDocker', 'initFiles', runJob],
        uploadResults: ['runJob', uploadResults],
        uploadArchive: ['runJob', uploadArchive],
        cleanup: ['uploadResults', 'uploadArchive', function(results, callback) {
            logger.info('Removing temporary directories');
            results.initFiles.tempDirCleanup();
            callback(null);
        }]
    }, (err) => {
        if (ERR(err, done)) return;
        done(null);
    });
}

function initDocker(info, callback) {
    const {
        context: {
            logger,
            docker,
            job: {
                image
            }
        }
    } = info;

    async.series([
        (callback) => {
            logger.info('Pinging docker');
            docker.ping((err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            const repository = util.parseRepositoryTag(image);
            const params = {
                fromImage: repository.repository,
                tag: repository.tag || 'latest'
            };

            docker.createImage(params, (err, stream) => {
                if (err) {
                    logger.warn(`Error pulling "${image}" image; attempting to fall back to cached version`);
                    logger.warn(err);
                }

                docker.modem.followProgress(stream, (err) => {
                    if (ERR(err, callback)) return;
                    callback(null);
                }, (output) => {
                    logger.info(output);
                });
            });
        },
    ], (err) => {
        if (ERR(err, callback)) return;
        callback(null);
    });
}

function initFiles(info, callback) {
    const {
        context: {
            logger,
            s3,
            job: {
                jobId,
                s3JobsBucket,
                entrypoint
            }
        }
    } = info;

    let jobArchiveFile, jobArchiveFileCleanup;
    const files = {};

    async.series([
        (callback) => {
            logger.info('Setting up temp file');
            tmp.file((err, file, fd, cleanup) => {
                if (ERR(err, callback)) return;
                jobArchiveFile = file;
                jobArchiveFileCleanup = cleanup;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Setting up temp dir');
            tmp.dir({
                prefix: `job_${jobId}_`,
                unsafeCleanup: true
            }, (err, dir, cleanup) => {
                if (ERR(err, callback)) return;
                files.tempDir = dir;
                files.tempDirCleanup = cleanup;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Loading job files');
            const params = {
                Bucket: s3JobsBucket,
                Key: `job_${jobId}.tar.gz`
            };
            s3.getObject(params).createReadStream()
            .on('error', (err) => {
                return ERR(err, callback);
            }).on('end', () => {
                callback(null);
            }).pipe(fs.createWriteStream(jobArchiveFile));
        },
        (callback) => {
            logger.info('Unzipping files');
            exec(`tar -xf ${jobArchiveFile} -C ${files.tempDir}`, (err) => {
                if (ERR(err, callback)) return;
                jobArchiveFileCleanup();
                callback(null);
            });
        },
        (callback) => {
            logger.info('Making entrypoint executable');
            exec(`chmod +x ${path.join(files.tempDir, entrypoint.slice(6))}`, (err) => {
                if (err) {
                    logger.error('Could not make file executable; continuing execution anyways');
                }
                callback(null);
            });
        }
    ], (err) => {
        if (ERR(err, callback)) return;
        callback(null, files);
    });
}

function runJob(info, callback) {
    const {
        context: {
            docker,
            logger,
            startTime,
            job: {
                jobId,
                image,
                entrypoint,
                s3JobsBucket,
                s3ResultsBucket,
                s3ArchivesBucket,
                webhookUrl,
                csrfToken,
                timeout
            }
        },
        initFiles: {
            tempDir
        }
    } = info;

    let results = {};
    let jobTimeout = timeout || 30;

    logger.info('Launching Docker container to run grading job');

    async.waterfall([
        (callback) => {
            const env = [
                `JOB_ID=${jobId}`,
                `ENTRYPOINT=${entrypoint}`,
                `S3_JOBS_BUCKET=${s3JobsBucket}`,
                `S3_RESULTS_BUCKET=${s3ResultsBucket}`,
                `S3_ARCHIVES_BUCKET=${s3ArchivesBucket}`,
                `WEBHOOK_URL=${webhookUrl}`,
                `CSRF_TOKEN=${csrfToken}`,
            ];
            if (config.devMode) {
                env.push(`AWS_ACCESS_KEY_ID=${config.awsConfig.accessKeyId}`);
                env.push(`AWS_SECRET_ACCESS_KEY=${config.awsConfig.secretAccessKey}`);
                env.push(`AWS_DEFAULT_REGION=${config.awsConfig.region}`);
            } else {
                env.push('AWS_DEFAULT_REGION=us-east-2');
            }
            docker.createContainer({
                Image: image,
                AttachStdout: true,
                AttachStderr: true,
                Tty: true,
                Env: env,
                HostConfig: {
                    Binds: [
                        `${tempDir}:/grade`
                    ]
                },
                Entrypoint: entrypoint.split(' ')
            }, (err, container) => {
                if (ERR(err, callback)) return;
                callback(null, container);
            });
        },
        (container, callback) => {
            container.attach({
                stream: true,
                stdout: true,
                stderr: true,
            }, (err, stream) => {
                if (ERR(err, callback)) return;
                const out = byline(stream);
                out.on('data', (line) => {
                    logger.info(`container> ${line.toString('utf8')}`);
                });
                callback(null, container);
            });
        },
        (container, callback) => {
            container.start((err) => {
                if (ERR(err, callback)) return;
                callback(null, container);
            });
        },
        (container, callback) => {
            const timeoutId = setTimeout(() => {
                results.timedOut = true;
                container.kill();
            }, jobTimeout * 1000);
            container.wait((err) => {
                clearTimeout(timeoutId);
                if (ERR(err, callback)) return;
                logger.info('Grading job completed');
                callback(null, container);
            });
        },
        (container, callback) => {
            container.inspect((err, data) => {
                if (ERR(err, callback)) return;
                results.succeeded = (!results.timedOut && data.State.ExitCode == 0);
                callback(null, container);
            });
        },
        (container, callback) => {
            container.remove((err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Reading course results');
            // Now that the job has completed, let's extract the results
            // First up: results.json
            if (results.succeeded) {
                fs.readFile(path.join(tempDir, 'results', 'results.json'), (err, data) => {
                    if (err) {
                        logger.error('Could not read results.json');
                        results.succeeded = false;
                    } else {
                        try {
                            results.results = JSON.parse(data);
                            results.succeeded = true;
                        } catch (e) {
                            logger.error('Could not parse results.json');
                            logger.error(e);
                            results.succeeded = false;
                            results.message = 'Could not parse the grading results.';
                        }
                        callback(null);
                    }
                });
            } else {
                if (results.timedOut) {
                    results.message = `Grading timed out after ${timeout} seconds.`;
                }
                results.results = null;
                callback(null);
            }
        }
    ], (err) => {
        results.job_id = jobId;
        results.start_time = startTime;
        results.end_time = new Date().toISOString();

        if (err) {
            results.end_time = new Date().toISOString();
            results.succeeded = false;
            results.message = err.toString();
            return callback(null, results);
        } else {
            return callback(null, results);
        }
    });
}

function uploadResults(info, callback) {
    const {
        context: {
            logger,
            s3,
            job: {
                jobId,
                s3ResultsBucket,
                webhookUrl
            }
        },
        runJob: results
    } = info;

    async.series([
        (callback) => {
            // Now we can send the results back to S3
            logger.info(`Uploading results.json to S3 bucket ${s3ResultsBucket}`);
            const params = {
                Bucket: s3ResultsBucket,
                Key: `job_${jobId}.json`,
                Body: new Buffer(JSON.stringify(results), 'binary')
            };
            s3.putObject(params, (err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            // Let's send the results back to PrairieLearn now; the archive will
            // be uploaded later
            if (webhookUrl) {
                logger.info('Pinging webhook with results');
                const webhookResults = {
                    data: results,
                    event: 'grading_result',
                    job_id: jobId
                };
                fetch(webhookUrl, {
                    method: 'POST',
                    body: JSON.stringify(webhookResults)
                }).then(() => callback(null)).catch((err) => {
                    return ERR(err, callback);
                });
            } else {
                callback(null);
            }
        }
    ], (err) => {
        if (ERR(err, callback)) return;
        callback(null);
    });
}

function uploadArchive(results, callback) {
    const {
        context: {
            logger,
            s3,
            job: {
                jobId,
                s3ArchivesBucket
            }
        },
        initFiles: {
            tempDir
        }
    } = results;

    let tempArchive, tempArchiveCleanup;
    async.series([
        // Now we can upload the archive of the /grade directory
        (callback) => {
            logger.info('Creating temp file for archive');
            tmp.file((err, file, fd, cleanup) => {
                if (ERR(err, callback)) return;
                tempArchive = file;
                tempArchiveCleanup = cleanup;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Building archive');
            exec(`tar -zcf ${tempArchive} ${tempDir}`, (err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            logger.info(`Uploading archive to s3 bucket ${s3ArchivesBucket}`);
            const params = {
                Bucket: s3ArchivesBucket,
                Key: `job_${jobId}.tar.gz`,
                Body: fs.createReadStream(tempArchive)
            };
            s3.upload(params, (err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
    ], (err) => {
        if (ERR(err, callback)) return;
        tempArchiveCleanup && tempArchiveCleanup();
        callback(null);
    });
}
<commit_msg>Remove object spread operator for better node compatibility<commit_after>const ERR = require('async-stacktrace');
const fs = require('fs-extra');
const async = require('async');
const tmp = require('tmp');
const Docker = require('dockerode');
const AWS = require('aws-sdk');
const { exec } = require('child_process');
const path = require('path');
const fetch = require('node-fetch');
const byline = require('byline');

const globalLogger = require('./lib/logger');
const config = require('./lib/config');
const queueReceiver = require('./lib/queueReceiver');
const util = require('./lib/util');

async.series([
    (callback) => {
        config.loadConfig((err) => {
            if (ERR(err, callback)) {
                globalLogger.error('Failed to load config; exiting process');
                process.exit(1);
            }
            callback(null);
        });
    },
    () => {
        globalLogger.info('Initialization complete; beginning to process jobs');
        queueReceiver(config.queueUrl, (message, logger, fail, success) => {
            handleMessage(message, logger, (err) => {
                if (ERR(err, fail)) return;
                success();
            });
        });
    }
]);

function handleMessage(messageBody, logger, done) {
    logger.info(`Grading job ${messageBody.jobId}!`);
    logger.info(messageBody);

    async.auto({
        context: function(callback) {
            logger.info('Creating context for job execution');
            const context = {
                docker: new Docker(),
                s3: new AWS.S3(),
                logger: logger,
                startTime: new Date().toISOString(),
                job: messageBody
            };
            callback(null, context);
        },
        initDocker: ['context', initDocker],
        initFiles: ['context', initFiles],
        runJob: ['initDocker', 'initFiles', runJob],
        uploadResults: ['runJob', uploadResults],
        uploadArchive: ['runJob', uploadArchive],
        cleanup: ['uploadResults', 'uploadArchive', function(results, callback) {
            logger.info('Removing temporary directories');
            results.initFiles.tempDirCleanup();
            callback(null);
        }]
    }, (err) => {
        if (ERR(err, done)) return;
        done(null);
    });
}

function initDocker(info, callback) {
    const {
        context: {
            logger,
            docker,
            job: {
                image
            }
        }
    } = info;

    async.series([
        (callback) => {
            logger.info('Pinging docker');
            docker.ping((err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            const repository = util.parseRepositoryTag(image);
            const params = {
                fromImage: repository.repository,
                tag: repository.tag || 'latest'
            };

            docker.createImage(params, (err, stream) => {
                if (err) {
                    logger.warn(`Error pulling "${image}" image; attempting to fall back to cached version`);
                    logger.warn(err);
                }

                docker.modem.followProgress(stream, (err) => {
                    if (ERR(err, callback)) return;
                    callback(null);
                }, (output) => {
                    logger.info(output);
                });
            });
        },
    ], (err) => {
        if (ERR(err, callback)) return;
        callback(null);
    });
}

function initFiles(info, callback) {
    const {
        context: {
            logger,
            s3,
            job: {
                jobId,
                s3JobsBucket,
                entrypoint
            }
        }
    } = info;

    let jobArchiveFile, jobArchiveFileCleanup;
    const files = {};

    async.series([
        (callback) => {
            logger.info('Setting up temp file');
            tmp.file((err, file, fd, cleanup) => {
                if (ERR(err, callback)) return;
                jobArchiveFile = file;
                jobArchiveFileCleanup = cleanup;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Setting up temp dir');
            tmp.dir({
                prefix: `job_${jobId}_`,
                unsafeCleanup: true
            }, (err, dir, cleanup) => {
                if (ERR(err, callback)) return;
                files.tempDir = dir;
                files.tempDirCleanup = cleanup;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Loading job files');
            const params = {
                Bucket: s3JobsBucket,
                Key: `job_${jobId}.tar.gz`
            };
            s3.getObject(params).createReadStream()
            .on('error', (err) => {
                return ERR(err, callback);
            }).on('end', () => {
                callback(null);
            }).pipe(fs.createWriteStream(jobArchiveFile));
        },
        (callback) => {
            logger.info('Unzipping files');
            exec(`tar -xf ${jobArchiveFile} -C ${files.tempDir}`, (err) => {
                if (ERR(err, callback)) return;
                jobArchiveFileCleanup();
                callback(null);
            });
        },
        (callback) => {
            logger.info('Making entrypoint executable');
            exec(`chmod +x ${path.join(files.tempDir, entrypoint.slice(6))}`, (err) => {
                if (err) {
                    logger.error('Could not make file executable; continuing execution anyways');
                }
                callback(null);
            });
        }
    ], (err) => {
        if (ERR(err, callback)) return;
        callback(null, files);
    });
}

function runJob(info, callback) {
    const {
        context: {
            docker,
            logger,
            startTime,
            job: {
                jobId,
                image,
                entrypoint,
                s3JobsBucket,
                s3ResultsBucket,
                s3ArchivesBucket,
                webhookUrl,
                csrfToken,
                timeout
            }
        },
        initFiles: {
            tempDir
        }
    } = info;

    let results = {};
    let jobTimeout = timeout || 30;

    logger.info('Launching Docker container to run grading job');

    async.waterfall([
        (callback) => {
            const env = [
                `JOB_ID=${jobId}`,
                `ENTRYPOINT=${entrypoint}`,
                `S3_JOBS_BUCKET=${s3JobsBucket}`,
                `S3_RESULTS_BUCKET=${s3ResultsBucket}`,
                `S3_ARCHIVES_BUCKET=${s3ArchivesBucket}`,
                `WEBHOOK_URL=${webhookUrl}`,
                `CSRF_TOKEN=${csrfToken}`,
            ];
            if (config.devMode) {
                env.push(`AWS_ACCESS_KEY_ID=${config.awsConfig.accessKeyId}`);
                env.push(`AWS_SECRET_ACCESS_KEY=${config.awsConfig.secretAccessKey}`);
                env.push(`AWS_DEFAULT_REGION=${config.awsConfig.region}`);
            } else {
                env.push('AWS_DEFAULT_REGION=us-east-2');
            }
            docker.createContainer({
                Image: image,
                AttachStdout: true,
                AttachStderr: true,
                Tty: true,
                Env: env,
                HostConfig: {
                    Binds: [
                        `${tempDir}:/grade`
                    ]
                },
                Entrypoint: entrypoint.split(' ')
            }, (err, container) => {
                if (ERR(err, callback)) return;
                callback(null, container);
            });
        },
        (container, callback) => {
            container.attach({
                stream: true,
                stdout: true,
                stderr: true,
            }, (err, stream) => {
                if (ERR(err, callback)) return;
                const out = byline(stream);
                out.on('data', (line) => {
                    logger.info(`container> ${line.toString('utf8')}`);
                });
                callback(null, container);
            });
        },
        (container, callback) => {
            container.start((err) => {
                if (ERR(err, callback)) return;
                callback(null, container);
            });
        },
        (container, callback) => {
            const timeoutId = setTimeout(() => {
                results.timedOut = true;
                container.kill();
            }, jobTimeout * 1000);
            container.wait((err) => {
                clearTimeout(timeoutId);
                if (ERR(err, callback)) return;
                logger.info('Grading job completed');
                callback(null, container);
            });
        },
        (container, callback) => {
            container.inspect((err, data) => {
                if (ERR(err, callback)) return;
                results.succeeded = (!results.timedOut && data.State.ExitCode == 0);
                callback(null, container);
            });
        },
        (container, callback) => {
            container.remove((err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Reading course results');
            // Now that the job has completed, let's extract the results
            // First up: results.json
            if (results.succeeded) {
                fs.readFile(path.join(tempDir, 'results', 'results.json'), (err, data) => {
                    if (err) {
                        logger.error('Could not read results.json');
                        results.succeeded = false;
                    } else {
                        try {
                            results.results = JSON.parse(data);
                            results.succeeded = true;
                        } catch (e) {
                            logger.error('Could not parse results.json');
                            logger.error(e);
                            results.succeeded = false;
                            results.message = 'Could not parse the grading results.';
                        }
                        callback(null);
                    }
                });
            } else {
                if (results.timedOut) {
                    results.message = `Grading timed out after ${timeout} seconds.`;
                }
                results.results = null;
                callback(null);
            }
        }
    ], (err) => {
        results.job_id = jobId;
        results.start_time = startTime;
        results.end_time = new Date().toISOString();

        if (err) {
            results.end_time = new Date().toISOString();
            results.succeeded = false;
            results.message = err.toString();
            return callback(null, results);
        } else {
            return callback(null, results);
        }
    });
}

function uploadResults(info, callback) {
    const {
        context: {
            logger,
            s3,
            job: {
                jobId,
                s3ResultsBucket,
                webhookUrl
            }
        },
        runJob: results
    } = info;

    async.series([
        (callback) => {
            // Now we can send the results back to S3
            logger.info(`Uploading results.json to S3 bucket ${s3ResultsBucket}`);
            const params = {
                Bucket: s3ResultsBucket,
                Key: `job_${jobId}.json`,
                Body: new Buffer(JSON.stringify(results), 'binary')
            };
            s3.putObject(params, (err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            // Let's send the results back to PrairieLearn now; the archive will
            // be uploaded later
            if (webhookUrl) {
                logger.info('Pinging webhook with results');
                const webhookResults = {
                    data: results,
                    event: 'grading_result',
                    job_id: jobId
                };
                fetch(webhookUrl, {
                    method: 'POST',
                    body: JSON.stringify(webhookResults)
                }).then(() => callback(null)).catch((err) => {
                    return ERR(err, callback);
                });
            } else {
                callback(null);
            }
        }
    ], (err) => {
        if (ERR(err, callback)) return;
        callback(null);
    });
}

function uploadArchive(results, callback) {
    const {
        context: {
            logger,
            s3,
            job: {
                jobId,
                s3ArchivesBucket
            }
        },
        initFiles: {
            tempDir
        }
    } = results;

    let tempArchive, tempArchiveCleanup;
    async.series([
        // Now we can upload the archive of the /grade directory
        (callback) => {
            logger.info('Creating temp file for archive');
            tmp.file((err, file, fd, cleanup) => {
                if (ERR(err, callback)) return;
                tempArchive = file;
                tempArchiveCleanup = cleanup;
                callback(null);
            });
        },
        (callback) => {
            logger.info('Building archive');
            exec(`tar -zcf ${tempArchive} ${tempDir}`, (err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
        (callback) => {
            logger.info(`Uploading archive to s3 bucket ${s3ArchivesBucket}`);
            const params = {
                Bucket: s3ArchivesBucket,
                Key: `job_${jobId}.tar.gz`,
                Body: fs.createReadStream(tempArchive)
            };
            s3.upload(params, (err) => {
                if (ERR(err, callback)) return;
                callback(null);
            });
        },
    ], (err) => {
        if (ERR(err, callback)) return;
        tempArchiveCleanup && tempArchiveCleanup();
        callback(null);
    });
}
<|endoftext|>


<commit_before>var aes = require('browserify-aes')
var assert = require('assert')
var bs58check = require('bs58check')
var createHash = require('create-hash')
var scrypt = require('scryptsy')
var xor = require('buffer-xor')

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

var BigInteger = require('bigi')

// constants
var SCRYPT_PARAMS = {
  N: 16384, // specified by BIP38
  r: 8,
  p: 8
}
var NULL = new Buffer(0)

function hash160 (buffer) {
  return createHash('rmd160').update(
    createHash('sha256').update(buffer).digest()
  ).digest()
}

function hash256 (buffer) {
  return createHash('sha256').update(
    createHash('sha256').update(buffer).digest()
  ).digest()
}

function getAddress (d, compressed) {
  var Q = curve.G.multiply(d).getEncoded(compressed)
  var hash = hash160(Q)
  var payload = new Buffer(21)
  payload.writeUInt8(0x00, 0) // XXX TODO FIXME bitcoin only??? damn you BIP38
  hash.copy(payload, 1)

  return bs58check.encode(payload)
}

function encryptRaw (buffer, compressed, passphrase, progressCallback, scryptParams) {
  if (buffer.length !== 32) throw new Error('Invalid private key length')
  scryptParams = scryptParams || SCRYPT_PARAMS

  var d = BigInteger.fromBuffer(buffer)
  var address = getAddress(d, compressed)
  var secret = new Buffer(passphrase, 'utf8')
  var salt = hash256(address).slice(0, 4)

  var N = scryptParams.N
  var r = scryptParams.r
  var p = scryptParams.p

  var scryptBuf = scrypt(secret, salt, N, r, p, 64, progressCallback)
  var derivedHalf1 = scryptBuf.slice(0, 32)
  var derivedHalf2 = scryptBuf.slice(32, 64)

  var xorBuf = xor(buffer, derivedHalf1)
  var cipher = aes.createCipheriv('aes-256-ecb', derivedHalf2, NULL)
  cipher.setAutoPadding(false)
  cipher.end(xorBuf)

  var cipherText = cipher.read()

  // 0x01 | 0x42 | flagByte | salt (4) | cipherText (32)
  var result = new Buffer(7 + 32)
  result.writeUInt8(0x01, 0)
  result.writeUInt8(0x42, 1)
  result.writeUInt8(compressed ? 0xe0 : 0xc0, 2)
  salt.copy(result, 3)
  cipherText.copy(result, 7)

  return result
}

function encrypt (buffer, compressed, passphrase, address, progressCallback, scryptParams) {
  return bs58check.encode(encryptRaw(buffer, compressed, passphrase, address, progressCallback, scryptParams))
}

// some of the techniques borrowed from: https://github.com/pointbiz/bitaddress.org
// todo: (optimization) init buffer in advance, and use copy instead of concat
function decryptRaw (buffer, passphrase, progressCallback, scryptParams) {
  // 39 bytes: 2 bytes prefix, 37 bytes payload
  if (buffer.length !== 39) throw new Error('Invalid BIP38 data length')
  if (buffer.readUInt8(0) !== 0x01) throw new Error('Invalid BIP38 prefix')
  scryptParams = scryptParams || SCRYPT_PARAMS

  // check if BIP38 EC multiply
  var type = buffer.readUInt8(1)
  if (type === 0x43) return decryptECMult(buffer, passphrase, progressCallback, scryptParams)
  if (type !== 0x42) throw new Error('Invalid BIP38 type')

  passphrase = new Buffer(passphrase, 'utf8')

  var flagByte = buffer.readUInt8(2)
  var compressed = flagByte === 0xe0
  if (!compressed && flagByte !== 0xc0) throw new Error('Invalid BIP38 compression flag')

  var N = scryptParams.N
  var r = scryptParams.r
  var p = scryptParams.p

  var salt = buffer.slice(3, 7)
  var scryptBuf = scrypt(passphrase, salt, N, r, p, 64, progressCallback)
  var derivedHalf1 = scryptBuf.slice(0, 32)
  var derivedHalf2 = scryptBuf.slice(32, 64)

  var privKeyBuf = buffer.slice(7, 7 + 32)
  var decipher = aes.createDecipheriv('aes-256-ecb', derivedHalf2, NULL)
  decipher.setAutoPadding(false)
  decipher.end(privKeyBuf)

  var plainText = decipher.read()
  var privateKey = xor(plainText, derivedHalf1)

  // verify salt matches address
  var d = BigInteger.fromBuffer(privateKey)
  var address = getAddress(d, compressed)
  var checksum = hash256(address).slice(0, 4)
  assert.deepEqual(salt, checksum)

  return {
    privateKey: privateKey,
    compressed: compressed
  }
}

function decrypt (string, passphrase, progressCallback, scryptParams) {
  return decryptRaw(bs58check.decode(string), passphrase, progressCallback, scryptParams)
}

function decryptECMult (buffer, passphrase, progressCallback, scryptParams) {
  passphrase = new Buffer(passphrase, 'utf8')
  buffer = buffer.slice(1) // FIXME: we can avoid this
  scryptParams = scryptParams || SCRYPT_PARAMS

  var flag = buffer.readUInt8(1)
  var compressed = (flag & 0x20) !== 0
  var hasLotSeq = (flag & 0x04) !== 0

  assert.equal((flag & 0x24), flag, 'Invalid private key.')

  var addressHash = buffer.slice(2, 6)
  var ownerEntropy = buffer.slice(6, 14)
  var ownerSalt

  // 4 bytes ownerSalt if 4 bytes lot/sequence
  if (hasLotSeq) {
    ownerSalt = ownerEntropy.slice(0, 4)

  // else, 8 bytes ownerSalt
  } else {
    ownerSalt = ownerEntropy
  }

  var encryptedPart1 = buffer.slice(14, 22) // First 8 bytes
  var encryptedPart2 = buffer.slice(22, 38) // 16 bytes

  var N = scryptParams.N
  var r = scryptParams.r
  var p = scryptParams.p
  var preFactor = scrypt(passphrase, ownerSalt, N, r, p, 32, progressCallback)

  var passFactor
  if (hasLotSeq) {
    var hashTarget = Buffer.concat([preFactor, ownerEntropy])
    passFactor = hash256(hashTarget)
  } else {
    passFactor = preFactor
  }

  var passInt = BigInteger.fromBuffer(passFactor)
  var passPoint = curve.G.multiply(passInt).getEncoded(true)

  var seedBPass = scrypt(passPoint, Buffer.concat([addressHash, ownerEntropy]), 1024, 1, 1, 64)
  var derivedHalf1 = seedBPass.slice(0, 32)
  var derivedHalf2 = seedBPass.slice(32, 64)

  var decipher = aes.createDecipheriv('aes-256-ecb', derivedHalf2, new Buffer(0))
  decipher.setAutoPadding(false)
  decipher.end(encryptedPart2)

  var decryptedPart2 = decipher.read()
  var tmp = xor(decryptedPart2, derivedHalf1.slice(16, 32))
  var seedBPart2 = tmp.slice(8, 16)

  var decipher2 = aes.createDecipheriv('aes-256-ecb', derivedHalf2, new Buffer(0))
  decipher2.setAutoPadding(false)
  decipher2.write(encryptedPart1) // first 8 bytes
  decipher2.end(tmp.slice(0, 8)) // last 8 bytes

  var seedBPart1 = xor(decipher2.read(), derivedHalf1.slice(0, 16))
  var seedB = Buffer.concat([seedBPart1, seedBPart2], 24)
  var factorB = BigInteger.fromBuffer(hash256(seedB))

  // d = passFactor * factorB (mod n)
  var d = passInt.multiply(factorB).mod(curve.n)

  return {
    privateKey: d.toBuffer(32),
    compressed: compressed
  }
}

function verify (string) {
  var decoded = bs58check.decodeUnsafe(string)
  if (!decoded) return false

  if (decoded.length !== 39) return false
  if (decoded.readUInt8(0) !== 0x01) return false

  var type = decoded.readUInt8(1)
  var flag = decoded.readUInt8(2)

  // encrypted WIF
  if (type === 0x42) {
    if (flag !== 0xc0 && flag !== 0xe0) return false

  // EC mult
  } else if (type === 0x43) {
    if ((flag & ~0x24)) return false
  } else {
    return false
  }

  return true
}

module.exports = {
  decrypt: decrypt,
  decryptECMult: decryptECMult,
  decryptRaw: decryptRaw,
  encrypt: encrypt,
  encryptRaw: encryptRaw,
  verify: verify
}
<commit_msg>remove deprecated TODO<commit_after>var aes = require('browserify-aes')
var assert = require('assert')
var bs58check = require('bs58check')
var createHash = require('create-hash')
var scrypt = require('scryptsy')
var xor = require('buffer-xor')

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

var BigInteger = require('bigi')

// constants
var SCRYPT_PARAMS = {
  N: 16384, // specified by BIP38
  r: 8,
  p: 8
}
var NULL = new Buffer(0)

function hash160 (buffer) {
  return createHash('rmd160').update(
    createHash('sha256').update(buffer).digest()
  ).digest()
}

function hash256 (buffer) {
  return createHash('sha256').update(
    createHash('sha256').update(buffer).digest()
  ).digest()
}

function getAddress (d, compressed) {
  var Q = curve.G.multiply(d).getEncoded(compressed)
  var hash = hash160(Q)
  var payload = new Buffer(21)
  payload.writeUInt8(0x00, 0) // XXX TODO FIXME bitcoin only??? damn you BIP38
  hash.copy(payload, 1)

  return bs58check.encode(payload)
}

function encryptRaw (buffer, compressed, passphrase, progressCallback, scryptParams) {
  if (buffer.length !== 32) throw new Error('Invalid private key length')
  scryptParams = scryptParams || SCRYPT_PARAMS

  var d = BigInteger.fromBuffer(buffer)
  var address = getAddress(d, compressed)
  var secret = new Buffer(passphrase, 'utf8')
  var salt = hash256(address).slice(0, 4)

  var N = scryptParams.N
  var r = scryptParams.r
  var p = scryptParams.p

  var scryptBuf = scrypt(secret, salt, N, r, p, 64, progressCallback)
  var derivedHalf1 = scryptBuf.slice(0, 32)
  var derivedHalf2 = scryptBuf.slice(32, 64)

  var xorBuf = xor(buffer, derivedHalf1)
  var cipher = aes.createCipheriv('aes-256-ecb', derivedHalf2, NULL)
  cipher.setAutoPadding(false)
  cipher.end(xorBuf)

  var cipherText = cipher.read()

  // 0x01 | 0x42 | flagByte | salt (4) | cipherText (32)
  var result = new Buffer(7 + 32)
  result.writeUInt8(0x01, 0)
  result.writeUInt8(0x42, 1)
  result.writeUInt8(compressed ? 0xe0 : 0xc0, 2)
  salt.copy(result, 3)
  cipherText.copy(result, 7)

  return result
}

function encrypt (buffer, compressed, passphrase, address, progressCallback, scryptParams) {
  return bs58check.encode(encryptRaw(buffer, compressed, passphrase, address, progressCallback, scryptParams))
}

// some of the techniques borrowed from: https://github.com/pointbiz/bitaddress.org
function decryptRaw (buffer, passphrase, progressCallback, scryptParams) {
  // 39 bytes: 2 bytes prefix, 37 bytes payload
  if (buffer.length !== 39) throw new Error('Invalid BIP38 data length')
  if (buffer.readUInt8(0) !== 0x01) throw new Error('Invalid BIP38 prefix')
  scryptParams = scryptParams || SCRYPT_PARAMS

  // check if BIP38 EC multiply
  var type = buffer.readUInt8(1)
  if (type === 0x43) return decryptECMult(buffer, passphrase, progressCallback, scryptParams)
  if (type !== 0x42) throw new Error('Invalid BIP38 type')

  passphrase = new Buffer(passphrase, 'utf8')

  var flagByte = buffer.readUInt8(2)
  var compressed = flagByte === 0xe0
  if (!compressed && flagByte !== 0xc0) throw new Error('Invalid BIP38 compression flag')

  var N = scryptParams.N
  var r = scryptParams.r
  var p = scryptParams.p

  var salt = buffer.slice(3, 7)
  var scryptBuf = scrypt(passphrase, salt, N, r, p, 64, progressCallback)
  var derivedHalf1 = scryptBuf.slice(0, 32)
  var derivedHalf2 = scryptBuf.slice(32, 64)

  var privKeyBuf = buffer.slice(7, 7 + 32)
  var decipher = aes.createDecipheriv('aes-256-ecb', derivedHalf2, NULL)
  decipher.setAutoPadding(false)
  decipher.end(privKeyBuf)

  var plainText = decipher.read()
  var privateKey = xor(plainText, derivedHalf1)

  // verify salt matches address
  var d = BigInteger.fromBuffer(privateKey)
  var address = getAddress(d, compressed)
  var checksum = hash256(address).slice(0, 4)
  assert.deepEqual(salt, checksum)

  return {
    privateKey: privateKey,
    compressed: compressed
  }
}

function decrypt (string, passphrase, progressCallback, scryptParams) {
  return decryptRaw(bs58check.decode(string), passphrase, progressCallback, scryptParams)
}

function decryptECMult (buffer, passphrase, progressCallback, scryptParams) {
  passphrase = new Buffer(passphrase, 'utf8')
  buffer = buffer.slice(1) // FIXME: we can avoid this
  scryptParams = scryptParams || SCRYPT_PARAMS

  var flag = buffer.readUInt8(1)
  var compressed = (flag & 0x20) !== 0
  var hasLotSeq = (flag & 0x04) !== 0

  assert.equal((flag & 0x24), flag, 'Invalid private key.')

  var addressHash = buffer.slice(2, 6)
  var ownerEntropy = buffer.slice(6, 14)
  var ownerSalt

  // 4 bytes ownerSalt if 4 bytes lot/sequence
  if (hasLotSeq) {
    ownerSalt = ownerEntropy.slice(0, 4)

  // else, 8 bytes ownerSalt
  } else {
    ownerSalt = ownerEntropy
  }

  var encryptedPart1 = buffer.slice(14, 22) // First 8 bytes
  var encryptedPart2 = buffer.slice(22, 38) // 16 bytes

  var N = scryptParams.N
  var r = scryptParams.r
  var p = scryptParams.p
  var preFactor = scrypt(passphrase, ownerSalt, N, r, p, 32, progressCallback)

  var passFactor
  if (hasLotSeq) {
    var hashTarget = Buffer.concat([preFactor, ownerEntropy])
    passFactor = hash256(hashTarget)
  } else {
    passFactor = preFactor
  }

  var passInt = BigInteger.fromBuffer(passFactor)
  var passPoint = curve.G.multiply(passInt).getEncoded(true)

  var seedBPass = scrypt(passPoint, Buffer.concat([addressHash, ownerEntropy]), 1024, 1, 1, 64)
  var derivedHalf1 = seedBPass.slice(0, 32)
  var derivedHalf2 = seedBPass.slice(32, 64)

  var decipher = aes.createDecipheriv('aes-256-ecb', derivedHalf2, new Buffer(0))
  decipher.setAutoPadding(false)
  decipher.end(encryptedPart2)

  var decryptedPart2 = decipher.read()
  var tmp = xor(decryptedPart2, derivedHalf1.slice(16, 32))
  var seedBPart2 = tmp.slice(8, 16)

  var decipher2 = aes.createDecipheriv('aes-256-ecb', derivedHalf2, new Buffer(0))
  decipher2.setAutoPadding(false)
  decipher2.write(encryptedPart1) // first 8 bytes
  decipher2.end(tmp.slice(0, 8)) // last 8 bytes

  var seedBPart1 = xor(decipher2.read(), derivedHalf1.slice(0, 16))
  var seedB = Buffer.concat([seedBPart1, seedBPart2], 24)
  var factorB = BigInteger.fromBuffer(hash256(seedB))

  // d = passFactor * factorB (mod n)
  var d = passInt.multiply(factorB).mod(curve.n)

  return {
    privateKey: d.toBuffer(32),
    compressed: compressed
  }
}

function verify (string) {
  var decoded = bs58check.decodeUnsafe(string)
  if (!decoded) return false

  if (decoded.length !== 39) return false
  if (decoded.readUInt8(0) !== 0x01) return false

  var type = decoded.readUInt8(1)
  var flag = decoded.readUInt8(2)

  // encrypted WIF
  if (type === 0x42) {
    if (flag !== 0xc0 && flag !== 0xe0) return false

  // EC mult
  } else if (type === 0x43) {
    if ((flag & ~0x24)) return false
  } else {
    return false
  }

  return true
}

module.exports = {
  decrypt: decrypt,
  decryptECMult: decryptECMult,
  decryptRaw: decryptRaw,
  encrypt: encrypt,
  encryptRaw: encryptRaw,
  verify: verify
}
<|endoftext|>


<commit_before>'use strict';

var seneca = require('seneca')();
var options = require('./config/seneca-options');
var cdBadges = require('./lib/cd-badges');

seneca.options(options);
seneca.log.info(
  'Seneca options',
  JSON.stringify(seneca.export('options'), null, 4)
);

seneca.use(cdBadges);
seneca.listen()
  .client({type: 'web', host: process.env.TARGETIP || '127.0.0.1', port: 10301, pin: 'role:cd-dojos,cmd:*'})
  .client({type: 'web', host: process.env.TARGETIP || '127.0.0.1', port: 10303, pin: 'role:cd-profiles,cmd:*'});
<commit_msg>Added DOCKER_HOST_IP env var<commit_after>'use strict';

var seneca = require('seneca')();
var options = require('./config/seneca-options');
var cdBadges = require('./lib/cd-badges');

seneca.options(options);
seneca.log.info(
  'Seneca options',
  JSON.stringify(seneca.export('options'), null, 4)
);

seneca.use(cdBadges);
seneca.listen()
  .client({type: 'web', host: process.env.DOCKER_HOST_IP || process.env.TARGETIP || '127.0.0.1', port: 10301, pin: 'role:cd-dojos,cmd:*'})
  .client({type: 'web', host: process.env.DOCKER_HOST_IP || process.env.TARGETIP || '127.0.0.1', port: 10303, pin: 'role:cd-profiles,cmd:*'});
<|endoftext|>


<commit_before>/**
 Copyright 2017 KiKe. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 **/
'use strict';
var Alexa = require('alexa-sdk');
var _ = require('lodash');
var data = require('./data');

var MOLECULE_ALEXA_STATE = {
    START: "STARTMODE",
    HELP: "HELPMODE"
};

var languageString = {
    "en": {
        "translation": {
            "WELCOME_MESSAGE": "Welcome to Molecule! You can ask me about any Molecules",
            "PROPERTIES": "%s of %s is %s"
        }
    }
};

exports.handler = function (event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.resources = languageString;
    alexa.registerHandlers(newSessionHandlers, startMoleculeHandlers);
    alexa.execute();
};

var newSessionHandlers = {
    "LaunchRequest": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.START;
        this.emitWithState("GetMolecules", this.event.request.intent.slots);
    },
    "GetMoleculeIntent": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.START;
        this.emitWithState("GetMolecules", this.event.request.intent.slots);
    },
    "AMAZON.StartOverIntent": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.START;
        this.emitWithState("GetMolecules", true);
    },
    "AMAZON.HelpIntent": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.HELP;
        this.emitWithState("helpIntent", true);
    },
    "Unhandled": function () {
        var speechOutput = this.t("START_UNHANDLED");
        this.emit(":ask", speechOutput, speechOutput);
    }
};

var startMoleculeHandlers = Alexa.CreateStateHandler(MOLECULE_ALEXA_STATE.START, {

    "GetMolecules": function (slots) {
        var moleculeName = slots.MoleculeName.value;
        var moleculeData = [];
        var _this = this;

        data.httpGet(moleculeName, function (result) {

            moleculeData = result.data;

            var dataIndex = _.findIndex(moleculeData, function (mol) {
                return mol.IUPACName.toLocaleLowerCase() == moleculeName.toLocaleLowerCase();
            });

            if (dataIndex != -1) {
                if (slots.Properties) {
                    var propertiesIndex = _.findIndex(moleculeData[dataIndex].properties, function (prop) {
                        return prop.valueTitle.toLocaleLowerCase() == slots.Properties.value.toLocaleLowerCase();
                    });

                    var proObj = moleculeData[dataIndex].properties[propertiesIndex];
                    var speechOutput = _this.t("PROPERTIES", proObj.valueTitle, moleculeName, proObj.valueData);
                }
            }

            if (speechOutput) {
                _this.emit(":tell", speechOutput);
            } else {
                _this.emit(":tell", _this.t("WELCOME_MESSAGE"));
            }

        });
    }
});

<commit_msg>Added chemical formula slot<commit_after>/**
 Copyright 2017 KiKe. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 **/
'use strict';
var Alexa = require('alexa-sdk');
var _ = require('lodash');
var data = require('./data');

var MOLECULE_ALEXA_STATE = {
    START: "STARTMODE",
    HELP: "HELPMODE"
};

var languageString = {
    "en": {
        "translation": {
            "WELCOME_MESSAGE": "Welcome to Molecule! You can ask me about any Molecules",
            "PROPERTIES": "%s of %s is %s",
            "CHEMICAL_FORMULA": "%s for %s is %s",
            "MOLECULE_MESSAGE": "I don't have any information for %s.",
            "PROPERTIES_MESSAGE": "I don't have any information on %s of %s."
        }
    }
};

exports.handler = function (event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.resources = languageString;
    alexa.registerHandlers(newSessionHandlers, startMoleculeHandlers);
    alexa.execute();
};

var newSessionHandlers = {
    "LaunchRequest": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.START;
        this.emitWithState("GetMolecules", this.event.request.intent.slots);
    },
    "GetMoleculeIntent": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.START;
        this.emitWithState("GetMolecules", this.event.request.intent.slots);
    },
    "AMAZON.StartOverIntent": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.START;
        this.emitWithState("GetMolecules", true);
    },
    "AMAZON.HelpIntent": function () {
        this.handler.state = MOLECULE_ALEXA_STATE.HELP;
        this.emitWithState("helpIntent", true);
    },
    "Unhandled": function () {
        var speechOutput = this.t("START_UNHANDLED");
        this.emit(":ask", speechOutput, speechOutput);
    }
};

var startMoleculeHandlers = Alexa.CreateStateHandler(MOLECULE_ALEXA_STATE.START, {

    "GetMolecules": function (slots) {
        var moleculeName = slots.MoleculeName.value;
        var moleculeData = [];
        var _this = this;
        var speechOutput;

        data.httpGet(moleculeName, function (result) {

            moleculeData = result.data;

            var dataIndex = _.findIndex(moleculeData, function (mol) {
                return mol.IUPACName.toLocaleLowerCase() == moleculeName.toLocaleLowerCase();
            });

            if (dataIndex != -1) {
                if (slots.Properties) {
                    var propertiesIndex = _.findIndex(moleculeData[dataIndex].properties, function (prop) {
                        return prop.valueTitle.toLocaleLowerCase() == slots.Properties.value.toLocaleLowerCase();
                    });

                    var proObj = moleculeData[dataIndex].properties[propertiesIndex];
                    speechOutput += _this.t("PROPERTIES", proObj.valueTitle, moleculeName, proObj.valueData);

                } else {
                    speechOutput += _this.t("PROPERTIES_MESSAGE", slots.Properties.value, moleculeName);
                }

                if (slots.ChemicalFormula) {

                    var cheObj = moleculeData[dataIndex].chemicalFormula;
                    speechOutput += _this.t("CHEMICAL_FORMULA", slots.ChemicalFormula.value, moleculeName, cheObj);

                } else {
                    speechOutput += _this.t("MOLECULE_MESSAGE", moleculeName);
                }

            } else {
                speechOutput += _this.t("MOLECULE_MESSAGE", moleculeName);
            }

            if (speechOutput) {
                _this.emit(":tell", speechOutput);
            } else {
                _this.emit(":tell", _this.t("WELCOME_MESSAGE"));
            }

        });
    }
});

<|endoftext|>


<commit_before>'use strict'
const most = require('most')
const request = require('request')
const EventEmitter = require('events')
const emitter = new EventEmitter()
const jsdom = require('jsdom')
const Promise = require('bluebird')
const _ = require('lodash/fp')

const startUrl = 'https://google.com'

const stream = most
  .fromEvent('html', emitter)
  .chain(x => {
    return most.fromPromise(new Promise((resolve, reject) => {
      jsdom.env(x, ['http://code.jquery.com/jquery.js'], (err, window) => {
        if (err) {
          reject(err)
        } else {
          let $ = window.$
          let links = $('a').toArray()

          let hrefs = _.reduce((acc, x) => {
            acc.push($(x).attr('href'))
            return acc
          }, [], links)

          resolve(hrefs)
        }
      })
    }))
  })

stream
  .subscribe({
    next: x => console.log('Data', x),
    complete: x => console.log('Finished', x),
    error: x => console.error('Error', x)
  })

request(startUrl, (err, response, body) => {
  emitter.emit('html', body)
})<commit_msg>Add stripUrls fn. Stream now returns A hrefs and IMG src props.<commit_after>'use strict'
const most = require('most')
const request = require('request')
const EventEmitter = require('events')
const emitter = new EventEmitter()
const jsdom = require('jsdom')
const Promise = require('bluebird')
const _ = require('lodash/fp')

const startUrl = 'https://google.com'

function stripUrls($, selector, prop) {
  let urls = $(selector)
    .toArray()
    .map(x => $(x).attr(prop))

  return urls
}

const stream = most
  .fromEvent('html', emitter)
  .chain(x => {
    return most.fromPromise(new Promise((resolve, reject) => {
      jsdom.env(x, ['http://code.jquery.com/jquery.js'], (err, window) => {
        if (err) {
          reject(err)
        } else {
          let $ = window.$
          let aHrefs = stripUrls($, 'a', 'href')
          let imgSrc = stripUrls($, 'img', 'src')

          let result = {
            aHrefs,
            imgSrc
          }

          resolve(result)
        }
      })
    }))
  })

stream
  .subscribe({
    next: x => console.log('Data', x),
    complete: x => console.log('Finished', x),
    error: x => console.error('Error', x)
  })

request(startUrl, (err, response, body) => {
  emitter.emit('html', body)
})<|endoftext|>


<commit_before>'use strict'

const Engine = require('engine')

exports.name = 'engine'
exports.outputFormat = 'html'

/**
 * Register all the provided helpers.
 */
function register(engine, helpers) {
  // Add all the helpers.
  for (const name in helpers || {}) {
    if ({}.hasOwnProperty.call(helpers, name)) {
      if (typeof helpers[name] === 'string') {
        // eslint-disable-next-line import/no-dynamic-require
        engine.helper(name, require(helpers[name]))
        continue
      }
      if (typeof helpers[name] === 'function') {
        engine.helper(name, helpers[name])
        continue
      }
      throw new Error('Invalid helpers type')
    }
  }
}

exports.compile = function (str, options) {
  const opts = Object.assign({}, options)
  const eng = new Engine(opts)
  register(eng, opts.helpers)

  return eng.compile(str, opts)
}
<commit_msg>Update syntax<commit_after>'use strict'

const Engine = require('engine')

exports.name = 'engine'
exports.outputFormat = 'html'

/**
 * Register all the provided helpers.
 */
function register(engine, helpers) {
  // Add all the helpers.
  for (const name in helpers || {}) {
    if ({}.hasOwnProperty.call(helpers, name)) {
      if (typeof helpers[name] === 'string') {
        engine.helper(name, require(helpers[name]))
        continue
      }

      if (typeof helpers[name] === 'function') {
        engine.helper(name, helpers[name])
        continue
      }

      throw new Error('Invalid helpers type')
    }
  }
}

exports.compile = function (str, options) {
  const opts = Object.assign({}, options)
  const eng = new Engine(opts)
  register(eng, opts.helpers)

  return eng.compile(str, opts)
}
<|endoftext|>


<commit_before>/*!
 * defaults-deep <https://github.com/jonschlinkert/defaults-deep>
 *
 * Copyright (c) 2014 Jon Schlinkert, contributors.
 * Licensed under the MIT license.
 */

'use strict';

var isObject = require('is-plain-object');
var slice = require('array-slice');
var forOwn = require('for-own');

module.exports = function defaults(o, objects) {
  if (o == null) return {};
  if (objects == null) return o;
  forEach(slice(arguments, 1), function (obj) {
    forOwn(obj, function (value, key) {
      var val = o[key];
      if (val == null) {
        o[key] = value;
      } else if (isObject(val) && isObject(value)) {
        defaults(val, value);
      }
    });
  });
  return o;
};

function forEach(arr, cb) {
  if (arr == null) return;
  var len = arr.length;
  var i = -1;

  while (++i < len) {
    if (cb(arr[i], i, arr) === false) {
      break;
    }
  }
}<commit_msg>fix function name<commit_after>/*!
 * defaults-deep <https://github.com/jonschlinkert/defaults-deep>
 *
 * Copyright (c) 2014 Jon Schlinkert, contributors.
 * Licensed under the MIT license.
 */

'use strict';

var isObject = require('is-plain-object');
var slice = require('array-slice');
var forOwn = require('for-own');

module.exports = function defaultsDeep(o, objects) {
  if (o == null) return {};
  if (objects == null) return o;
  forEach(slice(arguments, 1), function (obj) {
    forOwn(obj, function (value, key) {
      var val = o[key];
      if (val == null) {
        o[key] = value;
      } else if (isObject(val) && isObject(value)) {
        defaults(val, value);
      }
    });
  });
  return o;
};

function forEach(arr, cb) {
  if (arr == null) return;
  var len = arr.length;
  var i = -1;

  while (++i < len) {
    if (cb(arr[i], i, arr) === false) {
      break;
    }
  }
}<|endoftext|>


<commit_before>var ss = require('simple-statistics');
var inside = require('turf-inside');

module.exports = function(polyFC, ptFC, inField, outField, done){
  polyFC.features.forEach(function(poly){
    if(!poly.properties){
      poly.properties = {};
    }
    var values = [];
    ptFC.features.forEach(function(pt){
      if (inside(pt, poly)) {
        values.push(pt.properties[inField]);
      }
    })
    poly.properties[outField] = ss.sum(values);
  })

  return polyFC;
}
<commit_msg>Add JSDoc<commit_after>var ss = require('simple-statistics');
var inside = require('turf-inside');

/**
* Takes a set of polygons, a set of points, and tag polygons with the sum
* of point property values contained within.
*
* @module turf/sum
* @param {FeatureCollection} polygons a FeatureCollection of {@link Polygon} features
* @param {FeatureCollection} points a FeatureCollection of {@link Point} features
* @param {string} inField the field in input data to analyze
* @param {string} outField the field in which to store results
* @return {FeatureCollection} a FeatureCollection of {@link Polygon} features
* with properties listed as `outField` values in `aggregations`
* @example
* var polygons = turf.featurecollection([
*   turf.polygon([[[0,0],[10,0],[10,10],[0,10],[0,0]]]),
*   turf.polygon([[[10,0],[20,10],[20,20], [20,0]]])]);
* var points = turf.featurecollection([
*   turf.point(5,5, {population: 200}),
*   turf.point(1,3, {population: 600}),
*   turf.point(14,2, {population: 100}),
*   turf.point(13,1, {population: 200}),
*   turf.point(19,7, {population: 300})]);
* var aggregated = turf.sum(polygons, points, 'population', 'sum');
* //=polygons
* //=points
* //=aggregated
*/
module.exports = function(polyFC, ptFC, inField, outField){
  polyFC.features.forEach(function(poly){
    if(!poly.properties){
      poly.properties = {};
    }
    var values = [];
    ptFC.features.forEach(function(pt){
      if (inside(pt, poly)) {
        values.push(pt.properties[inField]);
      }
    });
    poly.properties[outField] = ss.sum(values);
  });

  return polyFC;
};
<|endoftext|>


<commit_before>
let SakuyaBot = require('./src/SakuyaBot')
let Twitter = require('twitter')
let TwitterClient = require('./src/TwitterClient')
let FollowCrawler = require('./src/FollowingCrawler')

// 環境変数よみこみ
require('dotenv').config()

let twitter = new Twitter ({
  consumer_key: process.env.consumer_key,
  consumer_secret: process.env.consumer_secret,
  access_token_key: process.env.access_token_key,
  access_token_secret: process.env.access_token_secret
})
let client = new TwitterClient(twitter)

// let sakuyaBot = new SakuyaBot(client)
// sakuyaBot.start()

// client.getIds(10, '1510396014174031000').then((res) => console.dir(res)).catch((err) => console.dir(err))

let autoRemove = new FollowCrawler(client)
autoRemove.start(5)

<commit_msg>Uncommented bot startup statement<commit_after>
let SakuyaBot = require('./src/SakuyaBot')
let Twitter = require('twitter')
let TwitterClient = require('./src/TwitterClient')
let FollowCrawler = require('./src/FollowingCrawler')

// 環境変数よみこみ
require('dotenv').config()

let twitter = new Twitter ({
  consumer_key: process.env.consumer_key,
  consumer_secret: process.env.consumer_secret,
  access_token_key: process.env.access_token_key,
  access_token_secret: process.env.access_token_secret
})
let client = new TwitterClient(twitter)

let sakuyaBot = new SakuyaBot(client)
sakuyaBot.start()

let autoRemove = new FollowCrawler(client)
autoRemove.start(5)

<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var Options = require('wrap-options');

function die(message) {
    console.error('[CONFIG]', message);
    process.exit(1);
}

if (!process.argv[2]) {
    die('Config path missing');
}

var configPath = path.resolve(process.argv[2]);

function parse(configText) {
    return new Options(JSON.parse(configText));
}

function loadSync() {
    var configText = fs.readFileSync(configPath, { encoding: 'utf8' });
    return parse(configText);
}

function load(callback) {
    fs.readFile(configPath, { encoding: 'utf8' }, function (err, configText) {
        var config;
        try {
            config = parse(configText);
        } catch (err) {
            return callback(new Error('Invalid config file: ' + err.message));
        }

        callback(null, config);
    });
}

var reloadListeners = [];

function watch(onReload) {
    reloadListeners.push(onReload);
}

function reload(callback) {
    load(function (error, config) {
        callback = callback || function () {};
        if (error) {
            callback(error);
        } else {
            exports.__proto__ = config;
            reloadListeners.forEach(function (listener) {
                listener(exports);
            });
            callback();
        }
    });
}

function Config() {
    this.watch = watch;
    this.reload = reload;
}

exports = module.exports = new Config();

try {
    exports.__proto__ = loadSync();
} catch (err) {
    die('Invalid config file: ' + err.message);
}
<commit_msg>support for config path in environment parameter<commit_after>var fs = require('fs');
var path = require('path');
var Options = require('wrap-options');

function die(message) {
    console.error('[CONFIG]', message);
    process.exit(1);
}

var configPath = process.env.CONFIG || process.argv[2];

if (!configPath) {
    die('Config path missing');
}

configPath = path.resolve(configPath);

function parse(configText) {
    return new Options(JSON.parse(configText));
}

function loadSync() {
    var configText = fs.readFileSync(configPath, { encoding: 'utf8' });
    return parse(configText);
}

function load(callback) {
    fs.readFile(configPath, { encoding: 'utf8' }, function (err, configText) {
        var config;
        try {
            config = parse(configText);
        } catch (err) {
            return callback(new Error('Invalid config file: ' + err.message));
        }

        callback(null, config);
    });
}

var reloadListeners = [];

function watch(onReload) {
    reloadListeners.push(onReload);
}

function reload(callback) {
    load(function (error, config) {
        callback = callback || function () {};
        if (error) {
            callback(error);
        } else {
            exports.__proto__ = config;
            reloadListeners.forEach(function (listener) {
                listener(exports);
            });
            callback();
        }
    });
}

function Config() {
    this.watch = watch;
    this.reload = reload;
}

exports = module.exports = new Config();

try {
    exports.__proto__ = loadSync();
} catch (err) {
    die('Invalid config file: ' + err.message);
}
<|endoftext|>


<commit_before>/* global window, module */

/**
 * Router
 *
 * @version: 0.1.1
 * @author Graidenix
 *
 * @constructor
 *
 * @param {object} options
 * @returns {Router}
 */
function Router(options) {
    var settings = this._getSettings(options);

    this.routes = settings.routes;
    this.notFoundHandler = settings.page404;
    this.mode = (!window.history || !window.history.pushState) ? 'hash' : settings.mode;
    this.root = settings.root === '/' ? '/' : '/' + this._trimSlashes(settings.root) + '/';
    this._pageState = null;

    return this;
}

/**
 * Define Router Page
 *
 * @param {string} uri
 * @param {object} query
 * @param {Array} params
 * @param {object} state
 *
 * @constructor
 */
Router.Page = function (uri, query, params, state) {
    this.uri = uri || '';
    this.query = query || {};
    this.params = params || [];
    this.state = state || null;
};

/**
 * Sanitize options and add default values
 *
 * @param {object} options
 * @returns {object}
 * @private
 */
Router.prototype._getSettings = function (options) {
    var settings = {};
    var defaults = {
        routes: [],
        mode: 'history',
        root: '/',
        page404: function (page) {
            console.error({
                page: page,
                message: '404. Page not found'
            });
        }
    };

    options = options || {};
    ['routes', 'mode', 'root', 'page404'].forEach(function (key) {
        settings[key] = options[key] || defaults[key];
    });

    return settings;
};

/**
 * Get URI for Router 'history' mode
 *
 * @private
 * @returns {string}
 */
Router.prototype._getHistoryFragment = function () {
    var fragment = decodeURI(window.location.pathname);
    if (this.root !== '/') {
        fragment = fragment.replace(this.root, '');
    }
    return this._trimSlashes(fragment);
};

/**
 * Get URI for router 'hash' mode
 *
 * @private
 * @returns {string}
 */
Router.prototype._getHashFragment = function () {
    var hash = window.location.hash.substr(1).replace(/(\?.*)$/, '');
    return this._trimSlashes(hash);
};

/**
 * Get current URI
 *
 * @private
 * @returns {string}
 */
Router.prototype._getFragment = function () {
    if (this.mode === 'history') {
        return this._getHistoryFragment();
    } else {
        return this._getHashFragment();
    }
};

/**
 * Trim slashes for path
 *
 * @private
 * @param {string} path
 * @returns {string}
 */
Router.prototype._trimSlashes = function (path) {
    if (typeof path !== 'string') {
        return '';
    }
    return path.toString().replace(/\/$/, '').replace(/^\//, '');
};

/**
 * 404 Page Handler
 *
 * @private
 */
Router.prototype._page404 = function (path) {
    this.notFoundHandler(path);
};

/**
 * Convert the string route rule to RegExp rule
 *
 * @param {string} route
 * @returns {RegExp}
 * @private
 */
Router.prototype._parseRouteRule = function (route) {
    if (typeof route !== "string") {
        return route;
    }
    var uri = this._trimSlashes(route);
    var rule = uri
        .replace(/([\\\/\-\_\.])/g, "\\$1")
        .replace(':word', '[a-zA-Z]+')
        .replace(':num', '\d+')
        .replace(':any', '[\\w\\-\\_\\.]+');

    return new RegExp('^' + rule + '$', 'i');
};

/**
 * Parse query string and return object for it
 *
 * @param {string} query
 * @returns {object}
 * @private
 */
Router.prototype._parseQuery = function (query) {
    var _query = {};
    if (typeof query !== 'string') {
        return _query;
    }

    if (query[0] === '?') {
        query = query.substr(1);
    }

    query.split('&').forEach(function (row) {
        var parts = row.split('=');
        if (parts[0] !== '') {
            if (parts[1] === undefined) {
                parts[1] = true;
            }
            _query[decodeURIComponent(parts[0])] = parts[1];
        }
    });
    return _query;
};

/**
 * Get query for `history` mode
 *
 * @returns {Object}
 * @private
 */
Router.prototype._getHistoryQuery = function () {
    return this._parseQuery(window.location.search);
};

/**
 * Get query for `hash` mode
 *
 * @returns {Object}
 * @private
 */
Router.prototype._getHashQuery = function () {
    var index = window.location.hash.indexOf('?');
    var query = (index !== -1) ? window.location.hash.substr(index) : "";
    return this._parseQuery(query);
};

/**
 * Get query as object
 *
 * @private
 * @returns {Object}
 */
Router.prototype._getQuery = function () {
    if (this.mode === 'history') {
        return this._getHistoryQuery();
    } else {
        return this._getHashQuery();
    }
};

/**
 * Add route to routes list
 *
 * @param {string|RegExp} rule
 * @param {function} handler
 * @returns {Router}
 */
Router.prototype.add = function (rule, handler) {
    this.routes.push({
        rule: this._parseRouteRule(rule),
        handler: handler
    });
    return this;
};

/**
 * Remove a route from routes list
 *
 * @param param
 * @returns {Router}
 */
Router.prototype.remove = function (param) {
    var self = this;
    if (typeof param === 'string') {
        param = this._parseRouteRule(param).toString();
    }
    this.routes.some(function (route, i) {
        if (route.handler === param || route.rule.toString() === param) {
            self.routes.splice(i, 1);
            return true;
        }
        return false;
    });

    return this;
};

/**
 * Reset the state of Router
 *
 * @returns {Router}
 */
Router.prototype.reset = function () {
    this.routes = [];
    this.mode = null;
    this.root = '/';
    this._pageState = {};
    this.removeUriListener();

    return this;
};

/**
 * Check the URL and execute handler for its route
 *
 * @returns {Router}
 */
Router.prototype.check = function () {
    var fragment = this._getFragment();
    var self = this;
    var found = this.routes.some(function (route) {
        var match = fragment.match(route.rule);
        if (match) {
            match.shift();
            var query = self._getQuery();
            var page = new Router.Page(fragment, query, match, self._pageState);
            route.handler.apply(page, match);
            self._current = btoa(window.location.href);
            self._pageState = null;
            return true;
        }
        return false;
    });

    if (!found) {
        self._current = btoa(window.location.href);
        this._page404(fragment);
    }

    return this;
};

/**
 * Add the URI listener
 *
 * @returns {Router}
 */
Router.prototype.addUriListener = function () {
    var self = this;
    this._current = btoa(window.location.href);

    window.clearInterval(this._interval);
    this._interval = setInterval(function () {
        if (self._current !== btoa(window.location.href)) {
            self.check();
        }
    }, 100);
    return this;
};

/**
 * Remove the URI listener
 *
 * @returns {Router}
 */
Router.prototype.removeUriListener = function () {
    window.clearInterval(this._interval);
    this._current = null;
    return this;
};

/**
 * Navigate to a page
 *
 * @param {string} path
 * @param {object} state
 *
 * @returns {Router}
 */
Router.prototype.navigateTo = function (path, state) {
    path = this._trimSlashes(path) || '';
    this._pageState = state || null;
    if (this.mode === 'history') {
        history.pushState(state, null, this.root + this._trimSlashes(path));
    } else {
        window.location.hash = path;
    }
    return this.check();
};

if (typeof window !== "undefined") {
    window.Router = Router;
}

if (typeof module !== "undefined") {
    module.exports = Router;
}
<commit_msg>fixed<commit_after>/* global window, module */

/**
 * Router
 *
 * @version: 0.1.1
 * @author Graidenix
 *
 * @constructor
 *
 * @param {object} options
 * @returns {Router}
 */
function Router(options) {
    var settings = this._getSettings(options);

    this.routes = settings.routes;
    this.notFoundHandler = settings.page404;
    this.mode = (!window.history || !window.history.pushState) ? 'hash' : settings.mode;
    this.root = settings.root === '/' ? '/' : '/' + this._trimSlashes(settings.root) + '/';
    this._pageState = null;

    return this;
}

/**
 * Define Router Page
 *
 * @param {string} uri
 * @param {object} query
 * @param {Array} params
 * @param {object} state
 *
 * @constructor
 */
Router.Page = function (uri, query, params, state) {
    this.uri = uri || '';
    this.query = query || {};
    this.params = params || [];
    this.state = state || null;
};

/**
 * Sanitize options and add default values
 *
 * @param {object} options
 * @returns {object}
 * @private
 */
Router.prototype._getSettings = function (options) {
    var settings = {};
    var defaults = {
        routes: [],
        mode: 'history',
        root: '/',
        page404: function (page) {
            console.error({
                page: page,
                message: '404. Page not found'
            });
        }
    };

    options = options || {};
    ['routes', 'mode', 'root', 'page404'].forEach(function (key) {
        settings[key] = options[key] || defaults[key];
    });

    return settings;
};

/**
 * Get URI for Router 'history' mode
 *
 * @private
 * @returns {string}
 */
Router.prototype._getHistoryFragment = function () {
    var fragment = decodeURI(window.location.pathname);
    if (this.root !== '/') {
        fragment = fragment.replace(this.root, '');
    }
    return this._trimSlashes(fragment);
};

/**
 * Get URI for router 'hash' mode
 *
 * @private
 * @returns {string}
 */
Router.prototype._getHashFragment = function () {
    var hash = window.location.hash.substr(1).replace(/(\?.*)$/, '');
    return this._trimSlashes(hash);
};

/**
 * Get current URI
 *
 * @private
 * @returns {string}
 */
Router.prototype._getFragment = function () {
    if (this.mode === 'history') {
        return this._getHistoryFragment();
    } else {
        return this._getHashFragment();
    }
};

/**
 * Trim slashes for path
 *
 * @private
 * @param {string} path
 * @returns {string}
 */
Router.prototype._trimSlashes = function (path) {
    if (typeof path !== 'string') {
        return '';
    }
    return path.toString().replace(/\/$/, '').replace(/^\//, '');
};

/**
 * 404 Page Handler
 *
 * @private
 */
Router.prototype._page404 = function (path) {
    this.notFoundHandler(path);
};

/**
 * Convert the string route rule to RegExp rule
 *
 * @param {string} route
 * @returns {RegExp}
 * @private
 */
Router.prototype._parseRouteRule = function (route) {
    if (typeof route !== "string") {
        return route;
    }
    var uri = this._trimSlashes(route);
    var rule = uri
        .replace(/([\\\/\-\_\.])/g, "\\$1")
        .replace(/\:word/g, '[a-zA-Z]+')
        .replace(/\:num/g, '\d+')
        .replace(/\{[a-zA-Z]+\}/, ':any')
        .replace(/\:any/g, '[\\w\\-\\_\\.]+');

    return new RegExp('^' + rule + '$', 'i');
};

/**
 * Parse query string and return object for it
 *
 * @param {string} query
 * @returns {object}
 * @private
 */
Router.prototype._parseQuery = function (query) {
    var _query = {};
    if (typeof query !== 'string') {
        return _query;
    }

    if (query[0] === '?') {
        query = query.substr(1);
    }

    query.split('&').forEach(function (row) {
        var parts = row.split('=');
        if (parts[0] !== '') {
            if (parts[1] === undefined) {
                parts[1] = true;
            }
            _query[decodeURIComponent(parts[0])] = parts[1];
        }
    });
    return _query;
};

/**
 * Get query for `history` mode
 *
 * @returns {Object}
 * @private
 */
Router.prototype._getHistoryQuery = function () {
    return this._parseQuery(window.location.search);
};

/**
 * Get query for `hash` mode
 *
 * @returns {Object}
 * @private
 */
Router.prototype._getHashQuery = function () {
    var index = window.location.hash.indexOf('?');
    var query = (index !== -1) ? window.location.hash.substr(index) : "";
    return this._parseQuery(query);
};

/**
 * Get query as object
 *
 * @private
 * @returns {Object}
 */
Router.prototype._getQuery = function () {
    if (this.mode === 'history') {
        return this._getHistoryQuery();
    } else {
        return this._getHashQuery();
    }
};

/**
 * Add route to routes list
 *
 * @param {string|RegExp} rule
 * @param {function} handler
 * @returns {Router}
 */
Router.prototype.add = function (rule, handler) {
    this.routes.push({
        rule: this._parseRouteRule(rule),
        handler: handler
    });
    return this;
};

/**
 * Remove a route from routes list
 *
 * @param param
 * @returns {Router}
 */
Router.prototype.remove = function (param) {
    var self = this;
    if (typeof param === 'string') {
        param = this._parseRouteRule(param).toString();
    }
    this.routes.some(function (route, i) {
        if (route.handler === param || route.rule.toString() === param) {
            self.routes.splice(i, 1);
            return true;
        }
        return false;
    });

    return this;
};

/**
 * Reset the state of Router
 *
 * @returns {Router}
 */
Router.prototype.reset = function () {
    this.routes = [];
    this.mode = null;
    this.root = '/';
    this._pageState = {};
    this.removeUriListener();

    return this;
};

/**
 * Check the URL and execute handler for its route
 *
 * @returns {Router}
 */
Router.prototype.check = function () {
    var fragment = this._getFragment();
    var self = this;
    var found = this.routes.some(function (route) {
        var match = fragment.match(route.rule);
        if (match) {
            match.shift();
            var query = self._getQuery();
            var page = new Router.Page(fragment, query, match, self._pageState);
            route.handler.apply(page, match);
            self._current = btoa(window.location.href);
            self._pageState = null;
            return true;
        }
        return false;
    });

    if (!found) {
        self._current = btoa(window.location.href);
        this._page404(fragment);
    }

    return this;
};

/**
 * Add the URI listener
 *
 * @returns {Router}
 */
Router.prototype.addUriListener = function () {
    var self = this;
    this._current = btoa(window.location.href);

    window.clearInterval(this._interval);
    this._interval = setInterval(function () {
        if (self._current !== btoa(window.location.href)) {
            self.check();
        }
    }, 100);
    return this;
};

/**
 * Remove the URI listener
 *
 * @returns {Router}
 */
Router.prototype.removeUriListener = function () {
    window.clearInterval(this._interval);
    this._current = null;
    return this;
};

/**
 * Navigate to a page
 *
 * @param {string} path
 * @param {object} state
 *
 * @returns {Router}
 */
Router.prototype.navigateTo = function (path, state) {
    path = this._trimSlashes(path) || '';
    this._pageState = state || null;
    if (this.mode === 'history') {
        history.pushState(state, null, this.root + this._trimSlashes(path));
    } else {
        window.location.hash = path;
    }
    return this.check();
};

if (typeof window !== "undefined") {
    window.Router = Router;
}

if (typeof module !== "undefined") {
    module.exports = Router;
}
<|endoftext|>


<commit_before>const register = (server, options) => {
    process.on('SIGINT', () => {
        server.log(['info', 'pm2', 'shutdown'], 'stopping hapi...');

        server.stop(options).then(() => {
            server.log(['info', 'pm2', 'shutdown'], 'hapi stopped');
            return process.exit(0);
        });
    });
};

exports.plugin = {
    register,
    pkg: require('./package.json')
};
<commit_msg>add async/await<commit_after>const register = (server, options) => {
    process.on('SIGINT', async () => {
        server.log(['info', 'pm2', 'shutdown'], 'stopping hapi...');
        await server.stop(options);
        server.log(['info', 'pm2', 'shutdown'], 'hapi stopped');

        return process.exit(0);
    });
};

exports.plugin = {
    register,
    pkg: require('./package.json')
};
<|endoftext|>


<commit_before><commit_msg>it works!<commit_after>var ZenIRCBot = require('zenircbot-api').ZenIRCBot
  , zen = new ZenIRCBot()
  , request = require('request')

zen.register_commands(
  "sparkfun.js",
  [{
    name: "/\\w\\w\\w-\\d\\d\\d\\d\\d/",
    description: "Looks up the part number on SparkFun"
  }]
)

function chop(str) {
  new_str = str.split('.')
  return new_str[0] + '.' + new_str[1].slice(0, 2)
}

var filtered = zen.filter({version: 1, type: 'privmsg'})
filtered.on('data', function(msg){
  var part = /\w\w\w-(\d\d\d\d\d)/i.exec(msg.data.message)
  if (part) {
    var number = parseInt(part[1], 10)
    var url = 'https://www.sparkfun.com/products/' + number.toString()
    request({
      url: url + '.json'
    }, function process(err, res, body) {
      if (err || res.statusCode !== 200) {
        return
      }
      var product = JSON.parse(body)
      if (part[0].toUpperCase() === product.sku.toUpperCase()) {
        var string = product.sku
        string += ': '
        string += product.name
        string += ' | $'
        string += chop(product.price)
        string += ' ('
        string += product.quantity
        string += ' left) | '
        string += url
        zen.send_privmsg(msg.data.channel, string)
      }
    })
  }
})
<|endoftext|>


<commit_before>'use strict';

var gutil = require('gulp-util'),
	Duplex = require('stream').Duplex,
	path = require('path');

module.exports = function () {
	var duplex = new Duplex({ objectMode: true, allowHalfOpen: true });

	duplex._write = function _write(file, encoding, done) {
		gutil.log('gulp-reload saw',
			gutil.colors.magenta(path.basename(file.path)),
			'and reloading now');

		duplex.unpipe();

		require('shelljs').exec(process.argv.join(' '));

		process.exit(0);

		done();
	};

	duplex._read = function _read() { };

	return duplex;
};
<commit_msg>Added check for gulpfile.js<commit_after>'use strict';

var gutil = require('gulp-util'),
	Duplex = require('stream').Duplex,
	path = require('path');

module.exports = function () {
	var duplex = new Duplex({ objectMode: true, allowHalfOpen: true });

	duplex._write = function _write(file, encoding, done) {
		if (!(/gulpfile.js/).test(file.path)) { return; }

		gutil.log('gulp-reload saw',
			gutil.colors.magenta(path.basename(file.path)),
			'and reloading now');

		duplex.unpipe();

		require('shelljs').exec(process.argv.join(' '));

		process.exit(0);

		done();
	};

	duplex._read = function _read() { };

	return duplex;
};
<|endoftext|>


<commit_before>var typeforce = require('typeforce')

module.exports = function middlewareConstructor (type, strict) {
  var compiled = typeforce.compile(type)

  return function middleware (req, res, next) {
    try {
      typeforce(compiled, req.body, strict)
      next()
    } catch (e) {
      next(e)
    }
  }
}
<commit_msg>default to strict<commit_after>var typeforce = require('typeforce')

module.exports = function middlewareConstructor (type, strict) {
  if (strict === undefined) {
    strict = true
  }

  var compiled = typeforce.compile(type)

  return function middleware (req, res, next) {
    try {
      typeforce(compiled, req.body, strict)
      next()
    } catch (e) {
      next(e)
    }
  }
}
<|endoftext|>


<commit_before>/*
 acrobat-js - http://github.com/fabianonunes/acrobat-js
 Copyright (c) 2011, Fabiano Nunes
 Released under the BSD License.
*/
var AcrobatJs = {

	paths : {
		cert1 : '/c/status1.pdf',
		cert6 : '/c/status6.pdf'
	},

	insertDoc : app.trustedFunction(function(path){
		app.beginPriv();
		this.insertPages ({
			nPage: this.numPages-1,
			cPath: path
		});
		this.pageNum = this.numPages-1;
		app.endPriv();
	}),

	addCert1 : function(){
		AcrobatJs.insertDoc(AcrobatJs.paths.cert1);
	},

	addCert6 : function(){

		AcrobatJs.insertDoc(AcrobatJs.paths.cert6);

		var f = this.getField('numproc')
			, mask = /[1-9]\d{0,6}-\d{2}\.\d{4}\.\d\.\d{2}\.\d{4}/;

		f.value = mask.exec(this.documentFileName) || 'Digite o número do processo';

	},

	sortBookmarks : function(root) {

		var returnTo = this.pageNum
			, chd = root.children
			, names = {}
			, key, bm;

		if(!chd) { return; }

		for(key = 0; bm = chd[key++];){
			bm.execute();
			bm.pageNum = this.pageNum;
			bm.order = key;
			names[bm.pageNum] = {};
			bm.children && AcrobatJs.sortBookmarks(bm);
		}

		chd.sort(function(a, b){
			return a.pageNum - b.pageNum || a.order - b.order;
		});

		for(key = 0; bm = chd[key++];){
			if(names[bm.pageNum][bm.name] && !bm.children){
				bm.remove();
				continue;
			}
			root.insertChild(bm, chd.length);
			names[bm.pageNum][bm.name] = true;
		}

		this.pageNum = returnTo;
	},

	initialize : function(){

		Utils.bindAll(AcrobatJs);

		var cEnable = "event.rc = (event.target != null);"
			, cExec = "AcrobatJs.sortBookmarks(this.bookmarkRoot);"
			, cLabel = "Ordenar &Marcadores";

		app.addMenuItem({
			cName: "sortBookmarks",
			cUser: cLabel,
			cParent: "Tools",
			cEnable: cEnable,
			cExec: cExec,
			nPos: 0
		});

		app.addToolButton({
			cName: "sortBkmButton",
			cLabel: cLabel,
			cEnable: cEnable,
			cExec: cExec,
			nPos: -1
		});

		app.addMenuItem({
			cName: "addCert6",
			cUser: "Certidão - Status &6",
			cParent: "Tools",
			cEnable: cEnable,
			cExec: "AcrobatJs.addCert6();",
			nPos: 0
		});

		app.addMenuItem({
			cName: "addCert1",
			cUser: "Certidão - Status &1",
			cParent: "Tools",
			cEnable: cEnable,
			cExec: "AcrobatJs.addCert1();",
			nPos: 0
		});

	}

}

var Utils = {

	bind : function bind(func) {
		return function() {
			return func.apply(event.target, Array.prototype.slice.call(arguments));
		};
	},

	bindAll : function(obj) {
		for (var key in obj) {
			if(Utils.isFunction(obj[key])){
				obj[key] = Utils.bind(obj[key]);
			}
		}
	},

	isFunction : function(obj) {
		return Object.prototype.toString.call(obj) == '[object Function]';
	}

}

AcrobatJs.initialize();
<commit_msg>renamed bind functions<commit_after>/*
 acrobat-js - http://github.com/fabianonunes/acrobat-js
 Copyright (c) 2011, Fabiano Nunes
 Released under the BSD License.
*/

var AcrobatJs = {

	paths : {
		cert1 : '/c/status1.pdf',
		cert6 : '/c/status6.pdf'
	},

	insertDoc : app.trustedFunction(function(path){
		app.beginPriv();
		this.insertPages({
			nPage: this.numPages-1,
			cPath: path
		});
		this.pageNum = this.numPages-1;
		app.endPriv();
	}),

	addCert6 : function(){

		AcrobatJs.insertDoc(AcrobatJs.paths.cert6);

		var f = this.getField('numproc')
			, mask = /[1-9]\d{0,6}-\d{2}\.\d{4}\.\d\.\d{2}\.\d{4}/;

		f.value = mask.exec(this.documentFileName) || 'Digite o número do processo';

	},

	sortBookmarks : function(root) {

		var returnTo = this.pageNum
			, chd = root.children
			, names = {}
			, key, bm;

		if(!chd) { return; }

		for(key = 0; bm = chd[key++];){
			bm.execute();
			bm.pageNum = this.pageNum;
			bm.order = key;
			names[bm.pageNum] = {};
			bm.children && AcrobatJs.sortBookmarks(bm);
		}

		chd.sort(function(a, b){
			return a.pageNum - b.pageNum || a.order - b.order;
		});

		for(key = 0; bm = chd[key++];){
			if(names[bm.pageNum][bm.name] && !bm.children){
				bm.remove();
				continue;
			}
			root.insertChild(bm, chd.length);
			names[bm.pageNum][bm.name] = true;
		}

		this.pageNum = returnTo;

	},

	initialize : function(){

		Utils.stickAll(AcrobatJs);

		var cEnable = "event.rc = (event.target != null);"
			, cExec = "AcrobatJs.sortBookmarks(this.bookmarkRoot);"
			, cLabel = "Ordenar &Marcadores";

		app.addMenuItem({
			cName: "sortBookmarks",
			cUser: cLabel,
			cParent: "Tools",
			cEnable: cEnable,
			cExec: cExec,
			nPos: 0
		});

		app.addToolButton({
			cName: "sortBkmButton",
			cLabel: cLabel,
			cEnable: cEnable,
			cExec: cExec,
			nPos: -1
		});

		app.addMenuItem({
			cName: "addCert6",
			cUser: "Certidão - Status &6",
			cParent: "Tools",
			cEnable: cEnable,
			cExec: "AcrobatJs.addCert6();",
			nPos: 0
		});

		app.addMenuItem({
			cName: "addCert1",
			cUser: "Certidão - Status &1",
			cParent: "Tools",
			cEnable: cEnable,
			cExec: "AcrobatJs.insertDoc(AcrobatJs.paths.cert1);",
			nPos: 0
		});

	}

}

var Utils = {

	stick : function(func) {
		return function() {
			return func.apply(event.target, Array.prototype.slice.call(arguments));
		}
	},

	stickAll : function(obj) {
		for (var key in obj) {
			if(Utils.isFunction(obj[key])){
				obj[key] = Utils.stick(obj[key]);
			}
		}
	},

	isFunction : function(obj) {
		return Object.prototype.toString.call(obj) == '[object Function]';
	}

}

AcrobatJs.initialize();
<|endoftext|>


<commit_before>/**
 * Simple Node based logger
 *
 * @param  object a.options
 *
 * @return object
 */
var plywood = function(settings) {
    // Api
    var a = {};

    // Standard logging methods and appropriate colors
    var standardMethods = {
        log: 'white',
        error: 'red',
        info: 'blue'
    };

    // Interval id
    var interval;

    // Counts active loops
    var loopCount = 0;

    // Adds a colored prefix
    function prefix(val, pre) {
        var color = a.options.prefixColor;

        if (typeof pre === 'undefined') {
            pre = a.options.prefix;
        }

        if (typeof pre === 'string') {
            if (a.colors[color]) {
                return a.colors[color](pre + ' ') + val;
            }

            return pre + ' ' + val;
        }

        return val;
    }

    // Adds a prefix to the first first element in an array
    function prefixArray(args, pre) {
        args[0] = prefix(args[0], pre);

        return args;
    }

    // Log with a color, prefix, and optional new line
    function log(color, prefix, inline) {
        return function() {
            var args = objectToArray(arguments);

            args = prefixArray(args, prefix);

            var output = args.join(' ');

            if (color && a.colors[color]) {
                output = a.colors[color](output);
            }

            a.logger.write(output);

            if (! inline) {
                a.logger.write('\n');
            }

            return output;
        }
    }

    function inline(val, prefix) {
        return log(false, prefix, true).apply(this, [val]);
    }

    // End the output, stop interval and apply callback
    function end(cb) {
        inline('\n', false);
        stopLoop();

        if (typeof cb === 'function') {
            cb();
        }
    }

    // Loop over an array of values n times
    function loop(vals, options) {
        options = setOptions(options, {
            repeat: 0,
            interval: 1000,
            prefix: true
        });

        var i = 0;
        var clear = parseInt(options.repeat) > 0;
        var firstVal = vals[i];

        loopCount ++;

        if (loopCount > 1) {
            inline('\r', false);
            stopLoop();
        }

        if (options.replace) {
            resetLine();
        } else if (options.prefix) {
            firstVal = prefix(firstVal, options.prefix);
        }

        inline(firstVal);

        if (vals.length > 1) {
            i ++;
        }

        interval = setInterval(function() {
            if (options.replace) {
                resetLine();
            }

            if (options.replace) {
                inline(vals[i]);
            } else {
                inline(vals[i], false);
            }
            i ++;

            if (i === vals.length) {
                if (clear && options.repeat < 2) {
                    end(options.end);
                }

                i = 0;
                options.repeat --;
            }
        }, options.interval);
    }

    // Stop the interval
    function stopLoop() {
        loopCount --;
        clearInterval(interval);
    }

    function resetLine() {
        if (a.logger.cursorTo && a.logger.clearLine) {
            a.logger.cursorTo(0);
            a.logger.clearLine();
        }
    }

    // Convert an object to an array
    function objectToArray(obj) {
        var arr = [];

        for (var p in obj) {
            arr.push(obj[p]);
        }

        return arr;
    }

    // Set an option
    function setOption(option, value) {
        if (option && value) {
            return a.options[option] = value;
        }

        return false;
    }

    function setOptions(options, defaults) {
        options = options || {};
        defaults = defaults || {};

        for (var prop in defaults) {
            if (typeof options[prop] === 'undefined') {
                options[prop] = defaults[prop];
            }
        }

        return options;
    }

    // Construct option
    function init() {
        // Constructor option fallback
        a.options = setOptions(settings, {
            prefix: '[' + require('./package').name + ']',
            prefixColor: 'cyan'
        });

        // Basic object properties
        a.colors = require('chalk');
        a.logger = process.stdout;

        // Setup standard methods with colors
        for (var p in standardMethods) {
            a[p] = log(standardMethods[p]);
        }

        // Extended methods
        a.inline = inline;
        a.end = end;
        a.loop = loop;
        a.set = setOption;

        return a;
    }

    // Return logger
    return init();

}

module.exports = plywood;
<commit_msg>Stop all loop intervals<commit_after>/**
 * Simple Node based logger
 *
 * @param  object a.options
 *
 * @return object
 */
var plywood = function(settings) {
    // Api
    var a = {};

    // Standard logging methods and appropriate colors
    var standardMethods = {
        log: 'white',
        error: 'red',
        info: 'blue'
    };

    // Interval id
    var interval;

    // Counts active loops
    var loopCount = 0;

    // Adds a colored prefix
    function prefix(val, pre) {
        var color = a.options.prefixColor;

        if (typeof pre === 'undefined') {
            pre = a.options.prefix;
        }

        if (typeof pre === 'string') {
            if (a.colors[color]) {
                return a.colors[color](pre + ' ') + val;
            }

            return pre + ' ' + val;
        }

        return val;
    }

    // Adds a prefix to the first first element in an array
    function prefixArray(args, pre) {
        args[0] = prefix(args[0], pre);

        return args;
    }

    // Log with a color, prefix, and optional new line
    function log(color, prefix, inline) {
        return function() {
            var args = objectToArray(arguments);

            args = prefixArray(args, prefix);

            var output = args.join(' ');

            if (color && a.colors[color]) {
                output = a.colors[color](output);
            }

            if (loopCount > 0 && ! inline) {
                a.logger.write('\n');
                stopLoop();
            }

            a.logger.write(output);

            if (! inline) {
                a.logger.write('\n');
            }

            return output;
        }
    }

    function inline(val, prefix) {
        return log(false, prefix, true).apply(this, [val]);
    }

    // End the output, stop interval and apply callback
    function end(cb) {
        inline('\n', false);
        stopLoop();

        if (typeof cb === 'function') {
            cb();
        }
    }

    // Loop over an array of values n times
    function loop(vals, options) {
        options = setOptions(options, {
            repeat: 0,
            interval: 1000,
            prefix: true
        });

        var i = 0;
        var clear = parseInt(options.repeat) > 0;
        var firstVal = vals[i];

        loopCount ++;

        if (loopCount > 1) {
            inline('\r', false);
            stopLoop();
        }

        if (options.replace) {
            resetLine();
        } else if (options.prefix) {
            firstVal = prefix(firstVal, options.prefix);
        }

        inline(firstVal);

        if (vals.length > 1) {
            i ++;
        }

        interval = setInterval(function() {
            if (options.replace) {
                resetLine();
            }

            if (options.replace) {
                inline(vals[i]);
            } else {
                inline(vals[i], false);
            }
            i ++;

            if (i === vals.length) {
                if (clear && options.repeat < 2) {
                    end(options.end);
                }

                i = 0;
                options.repeat --;
            }
        }, options.interval);
    }

    // Stop the interval
    function stopLoop() {
        loopCount --;
        clearInterval(interval);
    }

    function resetLine() {
        if (a.logger.cursorTo && a.logger.clearLine) {
            a.logger.cursorTo(0);
            a.logger.clearLine();
        }
    }

    // Convert an object to an array
    function objectToArray(obj) {
        var arr = [];

        for (var p in obj) {
            arr.push(obj[p]);
        }

        return arr;
    }

    // Set an option
    function setOption(option, value) {
        if (option && value) {
            return a.options[option] = value;
        }

        return false;
    }

    function setOptions(options, defaults) {
        options = options || {};
        defaults = defaults || {};

        for (var prop in defaults) {
            if (typeof options[prop] === 'undefined') {
                options[prop] = defaults[prop];
            }
        }

        return options;
    }

    // Construct option
    function init() {
        // Constructor option fallback
        a.options = setOptions(settings, {
            prefix: '[' + require('./package').name + ']',
            prefixColor: 'cyan'
        });

        // Basic object properties
        a.colors = require('chalk');
        a.logger = process.stdout;

        // Setup standard methods with colors
        for (var p in standardMethods) {
            a[p] = log(standardMethods[p]);
        }

        // Extended methods
        a.inline = inline;
        a.end = end;
        a.loop = loop;
        a.set = setOption;

        return a;
    }

    // Return logger
    return init();

}

module.exports = plywood;
<|endoftext|>


<commit_before>// Copyright (c) 2016, the ALMOsT project authors. Please see the
// AUTHORS file for details. All rights reserved. Use of this source code is
// governed by a MIT-style license that can be found in the LICENSE file.
/*jslint node: true*/
"use strict";

var createTransformer = require('./lib/transformer'),
    reducers = require('./lib/reducer'),
    Exception = require('./lib/exception');

//
exports.Exception = Exception;

// Maker Functions
exports.createTransformer = createTransformer;

// Helpers
exports.reduce = reducers.reduce;
exports.none = reducers.single;
exports.single = reducers.single;
exports.first = reducers.first;
exports.last = reducers.last;
exports.concat = reducers.concat;
exports.flatten = reducers.flatten;
exports.flattenDeep = reducers.flattenDeep;
exports.merge = reducers.merge;
<commit_msg>v1.0.0-alpha.7<commit_after>// Copyright (c) 2016, the ALMOsT project authors. Please see the
// AUTHORS file for details. All rights reserved. Use of this source code is
// governed by a MIT-style license that can be found in the LICENSE file.
/*jslint node: true*/
"use strict";

var createTransformer = require('./lib/transformer'),
    reducers = require('./lib/reducer'),
    Exception = require('./lib/exception');

//
exports.Exception = Exception;

// Maker Functions
exports.createTransformer = createTransformer;

// Helpers
exports.reduce = reducers.reduce;
exports.reduceBy = reducers.reduceBy;
exports.none = reducers.none;
exports.single = reducers.single;
exports.first = reducers.first;
exports.last = reducers.last;
exports.merge = reducers.merge;
exports.concat = reducers.concat;
exports.groupBy = reducers.groupBy;
exports.flatten = reducers.flatten;
exports.flattenDeep = reducers.flattenDeep;
<|endoftext|>