<commit_before>const _ = require('underscore');

const BaseCard = require('./basecard.js');
const CardWhenRevealed = require('./cardwhenrevealed.js');

class PlotCard extends BaseCard {
    constructor(owner, cardData) {
        super(owner, cardData);

        this.reserveModifier = 0;
        this.goldModifier = 0;
        this.initiativeModifier = 0;
        this.claimModifier = 0;
        this.claimSet = undefined;
    }

    whenRevealed(properties) {
        let whenClause = {
            when: {
                onPlotsWhenRevealed: event => event.plots.includes(this)
            }
        };
        let reaction = new CardWhenRevealed(this.game, this, _.extend(whenClause, properties));
        this.abilities.reactions.push(reaction);
    }

    hasRevealEffect() {
        return this.cardData.text && this.cardData.text.indexOf('When Revealed:') !== -1;
    }

    getInitiative() {
        var baseValue = this.canProvidePlotModifier['initiative'] ? this.cardData.initiative : 0;
        return baseValue + this.initiativeModifier;
    }

    getIncome() {
        let baseValue = this.canProvidePlotModifier['gold'] ? (this.baseIncome || this.getPrintedIncome()) : 0;

        return baseValue + this.goldModifier;
    }

    getPrintedIncome() {
        return this.cardData.income;
    }

    getReserve() {
        var baseValue = this.canProvidePlotModifier['reserve'] ? this.cardData.reserve : 0;
        return baseValue + this.reserveModifier;
    }

    getPrintedClaim() {
        return this.cardData.claim || 0;
    }

    getClaim() {
        let baseClaim = this.getPrintedClaim();

        if(_.isNumber(this.claimSet)) {
            return this.claimSet;
        }

        return baseClaim + this.claimModifier;
    }

    flipFaceup() {
        // This probably isn't necessary now
        this.facedown = false;

        // But this is
        this.selected = false;
    }
}

module.exports = PlotCard;
<commit_msg>Set claim minimum to 0 (#1686)<commit_after>const _ = require('underscore');

const BaseCard = require('./basecard.js');
const CardWhenRevealed = require('./cardwhenrevealed.js');

class PlotCard extends BaseCard {
    constructor(owner, cardData) {
        super(owner, cardData);

        this.reserveModifier = 0;
        this.goldModifier = 0;
        this.initiativeModifier = 0;
        this.claimModifier = 0;
        this.claimSet = undefined;
    }

    whenRevealed(properties) {
        let whenClause = {
            when: {
                onPlotsWhenRevealed: event => event.plots.includes(this)
            }
        };
        let reaction = new CardWhenRevealed(this.game, this, _.extend(whenClause, properties));
        this.abilities.reactions.push(reaction);
    }

    hasRevealEffect() {
        return this.cardData.text && this.cardData.text.indexOf('When Revealed:') !== -1;
    }

    getInitiative() {
        var baseValue = this.canProvidePlotModifier['initiative'] ? this.cardData.initiative : 0;
        return baseValue + this.initiativeModifier;
    }

    getIncome() {
        let baseValue = this.canProvidePlotModifier['gold'] ? (this.baseIncome || this.getPrintedIncome()) : 0;

        return baseValue + this.goldModifier;
    }

    getPrintedIncome() {
        return this.cardData.income;
    }

    getReserve() {
        var baseValue = this.canProvidePlotModifier['reserve'] ? this.cardData.reserve : 0;
        return baseValue + this.reserveModifier;
    }

    getPrintedClaim() {
        return this.cardData.claim || 0;
    }

    getClaim() {
        let baseClaim = this.getPrintedClaim();

        if(_.isNumber(this.claimSet)) {
            return this.claimSet;
        }

        return Math.max(baseClaim + this.claimModifier, 0);
    }

    flipFaceup() {
        // This probably isn't necessary now
        this.facedown = false;

        // But this is
        this.selected = false;
    }
}

module.exports = PlotCard;
<|endoftext|>


<commit_before>import net from "net";
import https from "https";
import crypto from "crypto";
import querystring from "querystring";
import ipAddress from "ip-address";
import request from "request";

function anonymizeIP(ip) {
    if (net.isIP(ip)) {
        const ipv4 = new ipAddress.Address4(ip + "/24");
        if (ipv4.isValid()) {
            return ipv4.startAddress().correctForm();
        }

        const ipv6 = new ipAddress.Address6(ip + "/48");
        if (ipv6.isValid()) {
            return ipv6.startAddress().correctForm();
        }
    }
    return undefined;
}

export default class {
    constructor(trackingId) {
        this._trackingId = trackingId;
        this._timeout = 1000;

        // Maximum number of measurements to fit into one batch. Google's
        // Measurement protocol limits this to 20.
        this._maxBatchLength = 20;
        // Maximum number of batches to keep in the buffer.
        this._maxBatchBufferLength = 50;
        this._batchBuffer = [];
        this._currentBatch = null;

        this._agent = new https.Agent({
            keepAlive: true,
            maxSockets: 1
        });
    }

    _request() {
        if (this._currentBatch !== null) {
            return;
        }
        if (this._batchBuffer.length === 0) {
            return;
        }

        this._currentBatch = this._batchBuffer.shift();

        const body = this._currentBatch.map(item => {
            return querystring.stringify(item.data);
        }).join("\n") + "\n";

        request.post("https://www.google-analytics.com/batch", {
            body: body,
            agent: this._agent,
            timeout: this._timeout
        }, (err, res) => {
            const batch = this._currentBatch;
            this._currentBatch = null;

            if (err) {
                batch.forEach(item => {
                    item.reject(err);
                });
            } else if (res.statusCode !== 200) {
                batch.forEach(item => {
                    item.reject(new Error(`Analytics request status ${res.statusCode}`));
                });
            } else {
                batch.forEach(item => {
                    item.resolve();
                });
            }

            this._request();
        });
    }

    _push(item) {
        if (this._batchBuffer.length === 0) {
            this._batchBuffer.push([]);
        }

        const lastBatch = this._batchBuffer[this._batchBuffer.length - 1];
        if (lastBatch.length < this._maxBatchLength) {
            lastBatch.push(item);
        } else {
            this._batchBuffer.push([item]);
        }

        if (this._batchBuffer.length > this._maxBatchBufferLength) {
            const dropped = this._batchBuffer.splice(0, this._batchBuffer.length - this._maxBatchBufferLength);
            dropped.forEach(item => {
                item.reject(new Error("Dropped"));
            });
        }

        this._request();
    }

    _send(req, ...overrides) {
        if (!this._trackingId) {
            return Promise.resolve();
        }

        const ip = anonymizeIP(req.get("x-appengine-user-ip") || req.ip);
        const ua = req.get("user-agent");
        const cid = crypto.createHash("sha256").update(ip + ua).digest("hex");

        const data = Object.assign({
            v: "1",
            tid: this._trackingId,
            cid: cid
        }, {
            dp: req.path,
            dr: req.get("referrer"), // Express considers "referrer" and "referer" interchangeable
            uip: ip,
            aip: "1",
            ua: ua
        }, ...overrides);

        return new Promise((resolve, reject) => {
            this._push({
                data: data,
                resolve: resolve,
                reject: reject
            });
        });
    }

    pageView(req) {
        return this._send(req, {
            t: "pageview",
        });
    }

    event(req, category, action, label, value) {
        return this._send(req, {
            t: "event",
            ec: category,
            ea: action,
            el: label,
            ev: value
        });
    }
}
<commit_msg>Fix analytics, don't send undefined fields<commit_after>import net from "net";
import https from "https";
import crypto from "crypto";
import querystring from "querystring";
import ipAddress from "ip-address";
import request from "request";

function clean(obj) {
    const result = {};

    Object.keys(obj).forEach(key => {
        if (obj[key] !== void 0) {
            result[key] = obj[key];
        }
    });

    return result;
}

function anonymizeIP(ip) {
    if (net.isIP(ip)) {
        const ipv4 = new ipAddress.Address4(ip + "/24");
        if (ipv4.isValid()) {
            return ipv4.startAddress().correctForm();
        }

        const ipv6 = new ipAddress.Address6(ip + "/48");
        if (ipv6.isValid()) {
            return ipv6.startAddress().correctForm();
        }
    }
    return void 0;
}

export default class {
    constructor(trackingId) {
        this._trackingId = trackingId;
        this._timeout = 1000;

        // Maximum number of measurements to fit into one batch. Google's
        // Measurement protocol limits this to 20.
        this._maxBatchLength = 20;
        // Maximum number of batches to keep in the buffer.
        this._maxBatchBufferLength = 50;
        this._batchBuffer = [];
        this._currentBatch = null;

        this._agent = new https.Agent({
            keepAlive: true,
            maxSockets: 1
        });
    }

    _request() {
        if (this._currentBatch !== null) {
            return;
        }
        if (this._batchBuffer.length === 0) {
            return;
        }

        this._currentBatch = this._batchBuffer.shift();

        const body = this._currentBatch.map(item => {
            return querystring.stringify(item.data);
        }).join("\n") + "\n";

        request.post("https://www.google-analytics.com/batch", {
            body: body,
            agent: this._agent,
            timeout: this._timeout
        }, (err, res) => {
            const batch = this._currentBatch;
            this._currentBatch = null;

            if (err) {
                batch.forEach(item => {
                    item.reject(err);
                });
            } else if (res.statusCode !== 200) {
                batch.forEach(item => {
                    item.reject(new Error(`Analytics request status ${res.statusCode}`));
                });
            } else {
                batch.forEach(item => {
                    item.resolve();
                });
            }

            this._request();
        });
    }

    _push(item) {
        if (this._batchBuffer.length === 0) {
            this._batchBuffer.push([]);
        }

        const lastBatch = this._batchBuffer[this._batchBuffer.length - 1];
        if (lastBatch.length < this._maxBatchLength) {
            lastBatch.push(item);
        } else {
            this._batchBuffer.push([item]);
        }

        if (this._batchBuffer.length > this._maxBatchBufferLength) {
            const dropped = this._batchBuffer.splice(0, this._batchBuffer.length - this._maxBatchBufferLength);
            dropped.forEach(item => {
                item.reject(new Error("Dropped"));
            });
        }

        this._request();
    }

    _send(req, ...overrides) {
        if (!this._trackingId) {
            return Promise.resolve();
        }

        const ip = anonymizeIP(req.get("x-appengine-user-ip") || req.ip);
        const ua = req.get("user-agent");
        const cid = crypto.createHash("sha256").update(ip + ua).digest("hex");

        const data = clean(
            Object.assign({
                v: "1",
                tid: this._trackingId,
                cid: cid
            }, {
                dp: req.path,
                dr: req.get("referrer"), // Express considers "referrer" and "referer" interchangeable
                uip: ip,
                aip: "1",
                ua: ua
            }, ...overrides)
        );

        return new Promise((resolve, reject) => {
            this._push({
                data: data,
                resolve: resolve,
                reject: reject
            });
        });
    }

    pageView(req) {
        return this._send(req, {
            t: "pageview",
        });
    }

    event(req, category, action, label, value) {
        return this._send(req, {
            t: "event",
            ec: category,
            ea: action,
            el: label,
            ev: value
        });
    }
}
<|endoftext|>


<commit_before>var express   = require('express');
var app       = module.exports = express();

var fs        = require('fs');
var passport  = require('passport');
var path      = require('path');
var resource  = require('./routes/resource');
var webshot = require('webshot');

app.get('/api/bower', function(req, res) {
  res.send(fs.readFileSync(__dirname + '/../../../bower.json'));
});

app.get('/api/package', function(req, res) {
  res.send(fs.readFileSync(__dirname + '/../../../package.json'));
});

app.get('/api/changelog', function(req, res) {
  res.send(fs.readFileSync(__dirname + '/../../../changelog.md'));
});

app.get('/pdftest', function(req, res) {
    console.log('starting pdftest');

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };

    webshot('google.com', options, function(err, renderStream) {

      console.log('starting pdftest - webshot done');

      var file = fs.createWriteStream('./temp/google.pdf', {encoding: 'binary'});

      renderStream.on('data', function(data) {

        console.log('starting pdftest - writing data');

        file.write(data.toString('binary'), 'binary');
      });
    });

});

app.get('/api/v1/quote/:id/pdf3', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = __dirname + '/../../../temp/' + req.params.id + '.pdf';
    fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

app.get('/api/v1/quote/:id/pdf2', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName =  './app/temp/' + req.params.id + '.pdf';
    //fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

app.get('/api/v1/quote/:id/pdf1', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = '/../../../tmp/' + req.params.id + '.pdf';
    fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

/*
app.get('/api/v1/quote/:id/download', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = './temp/' + req.params.id + '.pdf';

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        var pathToDownload = path.resolve(__dirname + '/../../../' + fileName);

        console.log('path is ' + pathToDownload);

        res.download(pathToDownload);
    });
});
*/

resource.setup(app);

/*
app.get('/api/me/auth',
  passport.authenticate('basic', { session: false }),
    function(req, res) {
        res.json(req.user);
});
*/

// Passport example
/*
var BasicStrategy = require('passport-http').BasicStrategy;

passport.use(new BasicStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      if (!user.validPassword(password)) { return done(null, false); }
      return done(null, user);
    });
  }
));

app.post('/api/wines', function(req, res) {
    passport.authenticate('local', function(req, res) {
        wine.addWine(req, res);
    });
});
*/
<commit_msg>More changes to path<commit_after>var express   = require('express');
var app       = module.exports = express();

var fs        = require('fs');
var passport  = require('passport');
var path      = require('path');
var resource  = require('./routes/resource');
var webshot = require('webshot');

app.get('/api/bower', function(req, res) {
  res.send(fs.readFileSync(__dirname + '/../../../bower.json'));
});

app.get('/api/package', function(req, res) {
  res.send(fs.readFileSync(__dirname + '/../../../package.json'));
});

app.get('/api/changelog', function(req, res) {
  res.send(fs.readFileSync(__dirname + '/../../../changelog.md'));
});

app.get('/pdftest', function(req, res) {
    console.log('starting pdftest');

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };

    webshot('google.com', options, function(err, renderStream) {

      console.log('starting pdftest - webshot done');

      var file = fs.createWriteStream('./temp/google.pdf', {encoding: 'binary'});

      renderStream.on('data', function(data) {

        console.log('starting pdftest - writing data');

        file.write(data.toString('binary'), 'binary');
      });
    });

});

app.get('/api/v1/quote/:id/pdf3', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = __dirname + '/../../../temp/' + req.params.id + '.pdf';
    fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

app.get('/api/v1/quote/:id/pdf2', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName =  './app/temp/' + req.params.id + '.pdf';
    //fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

app.get('/api/v1/quote/:id/pdf1a', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = '/../../../../tmp/' + req.params.id + '.pdf';
    fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

app.get('/api/v1/quote/:id/pdf1b', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = './../../../../tmp/' + req.params.id + '.pdf';
    fileName = path.resolve(fileName);

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        console.log('path is ' + fileName);

        //res.send(fs.readFileSync(__dirname + '/../../../temp/' + req.params.id + '.pdf'));

        res.download(fileName);
    });
});

/*
app.get('/api/v1/quote/:id/download', function(req, res) {

    console.log('generating pdf for quote id: ' + req.params.id);

    var url = app.get('base') + '#/tools/quoter/' + req.params.id + '/print';
    var fileName = './temp/' + req.params.id + '.pdf';

    console.log('fileName is ' + fileName);

    var options = {
        screenSize: {
            width: 320,
            height: 480
        },
        shotSize: {
            width: 320,
            height: 'all'
        },
        streamType: 'pdf',
        paperSize: {format: 'letter', orientation: 'portrait'},
        userAgent: 'Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_2 like Mac OS X; en-us)' + ' AppleWebKit/531.21.20 (KHTML, like Gecko) Mobile/7B298g'
    };
    webshot(url, fileName, options, function(err) {
        console.log('OK');

        var pathToDownload = path.resolve(__dirname + '/../../../' + fileName);

        console.log('path is ' + pathToDownload);

        res.download(pathToDownload);
    });
});
*/

resource.setup(app);

/*
app.get('/api/me/auth',
  passport.authenticate('basic', { session: false }),
    function(req, res) {
        res.json(req.user);
});
*/

// Passport example
/*
var BasicStrategy = require('passport-http').BasicStrategy;

passport.use(new BasicStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function (err, user) {
      if (err) { return done(err); }
      if (!user) { return done(null, false); }
      if (!user.validPassword(password)) { return done(null, false); }
      return done(null, user);
    });
  }
));

app.post('/api/wines', function(req, res) {
    passport.authenticate('local', function(req, res) {
        wine.addWine(req, res);
    });
});
*/
<|endoftext|>


<commit_before>/* KAAE Watch Scheduler */

import _ from 'lodash';
import later from 'later';
import doActions from './actions';

var Schedule = [];

function getCount(client) {
  return client.count({
    index:'watcher',
    type:"watch"
  });
}

function getWatcher(count,client) {
  return client.search({
    index:'watcher',
    type:"watch",
    size:count
  });
}

function doalert(server,client) {
  server.log(['status', 'debug', 'KaaE'], 'Reloading Watchers...');
  getCount(client).then(function(resp){
    getWatcher(resp.count,client).then(function(resp){
      _.each(resp.hits.hits, function(hit){

        if (Schedule[hit._id]) {
          if (_.isEqual(Schedule[hit._id].hit, hit)) { return; }
          else { server.log(['status', 'info', 'KaaE'],'Clearing watcher: '+hit._id); Schedule[hit._id].later.clear(); }
        }

          Schedule[hit._id] = {};
          Schedule[hit._id].hit = hit;

          if(hit._source.trigger.schedule.later){
            // https://bunkat.github.io/later/parsers.html#text
            var interval = later.parse.text(hit._source.trigger.schedule.later);
            Schedule[hit._id].interval = hit._source.trigger.schedule.later;
          }
          else if(hit._source.trigger.schedule.interval % 1 === 0){
            // max 60 seconds!
            var interval = later.parse.recur().every(hit._source.trigger.schedule.interval).second();
            Schedule[hit._id].interval = hit._source.trigger.schedule.interval;
          }

          if (hit._source.report) {
            /* Report */
            Schedule[hit._id].later = later.setInterval(function(){ reporting(hit,interval) }, interval);
            server.log(['status', 'info', 'KaaE'], 'Scheduled Report: '+hit._id+' every '+Schedule[hit._id].interval );
          } else {
            /* Watcher */
            Schedule[hit._id].later = later.setInterval(function(){ watching(hit,interval) }, interval);
            server.log(['status', 'info', 'KaaE'], 'Scheduled Watch: '+hit._id+' every '+Schedule[hit._id].interval );
          }

          function watching(task,interval) {
            server.log(['status', 'info', 'KaaE'], 'Executing watch: '+task._id+' Next Round of '+task._id+' at '+later.schedule(interval).next(1) );

            var watch = task._source;
            var request = watch.input.search.request;
            var condition = watch.condition.script.script;
            var transform = watch.transform.search ? watch.transform.search.request : {};
            var actions = watch.actions;

            client.search(request).then(function(payload){
              if (!payload) return;
              if (!condition) return;

              /* Validate Condition */
              try { var ret = eval(condition); } catch (err) {
                          server.log(['status', 'info', 'KaaE'], 'Condition Error for '+task._id+': '+err);
              }
              if (ret) {
                  /* Process Actions */
                  doActions(server,actions,payload);
                  /* Transform Query (disabled) */
                  // client.search(transform).then(function(payload) {
                  //     console.log('Transaction resp:',payload);
                  // });
              }
            });
        }
        function reporting(task,interval) {
          server.log(['status', 'info', 'KaaE'], 'Executing report: '+task._id+' Next round at '+later.schedule(interval).next(1) );
          var actions = task._source.actions;
          var payload = { "_id": task._id };
          if (!actions) { server.log(['status', 'info', 'KaaE'], 'Condition Error for '+task._id); return; }
          doActions(server,actions,payload);
        }
      });
    });
  });
}

module.exports = {
  doalert: doalert,
  getCount: getCount,
  getWatcher: getWatcher
};
<commit_msg>remove orphaned tasks<commit_after>/* KAAE Watch Scheduler */

import _ from 'lodash';
import later from 'later';
import doActions from './actions';

var Schedule = [];

function getCount(client) {
  return client.count({
    index:'watcher',
    type:"watch"
  });
}

function getWatcher(count,client) {
  return client.search({
    index:'watcher',
    type:"watch",
    size:count
  });
}

function doalert(server,client) {
  server.log(['status', 'debug', 'KaaE'], 'Reloading Watchers...');
  getCount(client).then(function(resp){
    getWatcher(resp.count,client).then(function(resp){
      /* Orphanizer */
        var orphans = _.difference(_.each(Object.keys( Schedule )), _.map(resp.hits.hits, '_id')  );
        _.each(orphans, function(orphan){
                server.log(['status', 'info', 'KaaE'],'Deleting orphan watcher: '+orphan);
                Schedule[orphan].later.clear();
                delete Schedule[orphan];
        });

      /* Scheduler */
      _.each(resp.hits.hits, function(hit){

        if (Schedule[hit._id]) {
          if (_.isEqual(Schedule[hit._id].hit, hit)) { return; }
          else { server.log(['status', 'info', 'KaaE'],'Clearing watcher: '+hit._id); Schedule[hit._id].later.clear(); }
        }

          Schedule[hit._id] = {};
          Schedule[hit._id].hit = hit;

          if(hit._source.trigger.schedule.later){
            // https://bunkat.github.io/later/parsers.html#text
            var interval = later.parse.text(hit._source.trigger.schedule.later);
            Schedule[hit._id].interval = hit._source.trigger.schedule.later;
          }
          else if(hit._source.trigger.schedule.interval % 1 === 0){
            // max 60 seconds!
            var interval = later.parse.recur().every(hit._source.trigger.schedule.interval).second();
            Schedule[hit._id].interval = hit._source.trigger.schedule.interval;
          }

          if (hit._source.report) {
            /* Report */
            Schedule[hit._id].later = later.setInterval(function(){ reporting(hit,interval) }, interval);
            server.log(['status', 'info', 'KaaE'], 'Scheduled Report: '+hit._id+' every '+Schedule[hit._id].interval );
          } else {
            /* Watcher */
            Schedule[hit._id].later = later.setInterval(function(){ watching(hit,interval) }, interval);
            server.log(['status', 'info', 'KaaE'], 'Scheduled Watch: '+hit._id+' every '+Schedule[hit._id].interval );
          }

          function watching(task,interval) {
            server.log(['status', 'info', 'KaaE'], 'Executing watch: '+task._id+' Next Round of '+task._id+' at '+later.schedule(interval).next(1) );

            var watch = task._source;
            var request = watch.input.search.request;
            var condition = watch.condition.script.script;
            var transform = watch.transform.search ? watch.transform.search.request : {};
            var actions = watch.actions;

            client.search(request).then(function(payload){
              if (!payload) return;
              if (!condition) return;

              /* Validate Condition */
              try { var ret = eval(condition); } catch (err) {
                          server.log(['status', 'info', 'KaaE'], 'Condition Error for '+task._id+': '+err);
              }
              if (ret) {
                  /* Process Actions */
                  doActions(server,actions,payload);
                  /* Transform Query (disabled) */
                  // client.search(transform).then(function(payload) {
                  //     console.log('Transaction resp:',payload);
                  // });
              }
            });
        }
        function reporting(task,interval) {
          server.log(['status', 'info', 'KaaE'], 'Executing report: '+task._id+' Next round at '+later.schedule(interval).next(1) );
          var actions = task._source.actions;
          var payload = { "_id": task._id };
          if (!actions) { server.log(['status', 'info', 'KaaE'], 'Condition Error for '+task._id); return; }
          doActions(server,actions,payload);
        }
      });
    });
  });
}

module.exports = {
  doalert: doalert,
  getCount: getCount,
  getWatcher: getWatcher
};
<|endoftext|>


<commit_before>/**
 * Dependencies.
 */
import config from 'config';
import Historical from 'sequelize-historical';
import slugify from 'limax';
import Promise from 'bluebird';
import showdown from 'showdown';
import { defaults, pick } from 'lodash';

import * as errors from '../graphql/errors';
import activities from '../constants/activities';
import { sanitizeObject } from '../lib/utils';
import { mustHaveRole } from '../lib/auth';

const markdownConverter = new showdown.Converter();

/**
 * Update Model.
 */
export default function(Sequelize, DataTypes) {
  const { models } = Sequelize;

  const Update = Sequelize.define(
    'Update',
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },

      slug: {
        type: DataTypes.STRING,
        unique: true,
        allowNull: false,
        set(slug) {
          if (slug && slug.toLowerCase) {
            this.setDataValue(
              'slug',
              slug
                .toLowerCase()
                .replace(/ /g, '-')
                .replace(/\./g, ''),
            );
          }
        },
      },

      CollectiveId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Collectives',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: false,
      },

      TierId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Tiers',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true,
      },

      FromCollectiveId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Collectives',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true,
      },

      CreatedByUserId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Users',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true, // non authenticated users can create a Update
      },

      LastEditedByUserId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Users',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true, // needs to be true because of old rows
      },

      title: {
        type: DataTypes.STRING,
        validate: {
          len: [1, 255],
        },
      },

      markdown: DataTypes.TEXT,
      html: {
        type: DataTypes.TEXT,
        get() {
          return this.getDataValue('markdown')
            ? markdownConverter.makeHtml(this.getDataValue('markdown'))
            : this.getDataValue('html');
        },
      },

      image: DataTypes.STRING,

      isPrivate: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },

      tags: {
        type: DataTypes.ARRAY(DataTypes.STRING),
      },

      publishedAt: {
        type: DataTypes.DATE,
      },

      createdAt: {
        type: DataTypes.DATE,
        defaultValue: Sequelize.NOW,
      },

      updatedAt: {
        type: DataTypes.DATE,
        defaultValue: Sequelize.NOW,
      },

      deletedAt: {
        type: DataTypes.DATE,
      },
    },
    {
      paranoid: true,

      getterMethods: {
        // Info.
        info() {
          return {
            id: this.id,
            title: this.title,
            html: this.html,
            image: this.image,
            createdAt: this.createdAt,
            updatedAt: this.updatedAt,
            publishedAt: this.publishedAt,
            slug: this.slug,
            tags: this.tags,
          };
        },
        minimal() {
          return {
            id: this.id,
            publishedAt: this.publishedAt,
            title: this.title,
            image: this.image,
            slug: this.slug,
          };
        },
        activity() {
          return {
            id: this.id,
            slug: this.slug,
            title: this.title,
            CollectiveId: this.CollectiveId,
            FromCollectiveId: this.FromCollectiveId,
            TierId: this.TierId,
          };
        },
      },

      hooks: {
        beforeValidate: instance => {
          if (!instance.publishedAt || !instance.slug) return instance.generateSlug();
        },
        beforeUpdate: instance => {
          if (!instance.publishedAt || !instance.slug) return instance.generateSlug();
        },
        afterCreate: instance => {
          models.Activity.create({
            type: activities.COLLECTIVE_UPDATE_CREATED,
            UserId: instance.LastEditedByUserId,
            CollectiveId: instance.CollectiveId,
            data: {
              update: instance.activity,
            },
          });
        },
      },
    },
  );

  /**
   * Instance Methods
   */

  // Edit an update
  Update.prototype.edit = async function(remoteUser, newUpdateData) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'edit this update');
    if (newUpdateData.TierId) {
      const tier = await models.Tier.findByPk(newUpdateData.TierId);
      if (!tier) {
        throw new errors.ValidationFailed({ message: 'Tier not found' });
      }
      if (tier.CollectiveId !== this.CollectiveId) {
        throw new errors.ValidationFailed({
          message: "Cannot link this update to a Tier that doesn't belong to this collective",
        });
      }
    }
    const editableAttributes = ['TierId', 'FromCollectiveId', 'title', 'html', 'markdown', 'image', 'tags'];
    sanitizeObject(newUpdateData, ['html', 'markdown']);
    return await this.update({
      ...pick(newUpdateData, editableAttributes),
      LastEditedByUserId: remoteUser.id,
    });
  };

  // Publish update
  Update.prototype.publish = async function(remoteUser) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'publish this update');
    this.publishedAt = new Date();
    this.collective = this.collective || (await models.Collective.findByPk(this.CollectiveId));
    models.Activity.create({
      type: activities.COLLECTIVE_UPDATE_PUBLISHED,
      UserId: remoteUser.id,
      CollectiveId: this.CollectiveId,
      data: {
        collective: this.collective.activity,
        update: this.activity,
        url: `${config.host.website}/${this.collective.slug}/updates/${this.slug}`,
      },
    });
    return await this.save();
  };

  // Unpublish update
  Update.prototype.unpublish = async function(remoteUser) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'unpublish this update');
    this.publishedAt = null;
    return await this.save();
  };

  Update.prototype.delete = async function(remoteUser) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'delete this update');
    return this.destroy();
  };

  // Returns the User model of the User that created this Update
  Update.prototype.getUser = function() {
    return models.User.findByPk(this.CreatedByUserId);
  };

  /*
   * If there is a username suggested, we'll check that it's valid or increase it's count
   * Otherwise, we'll suggest something.
   */
  Update.prototype.generateSlug = function() {
    if (!this.title) return;
    const suggestion = slugify(this.title.trim()).toLowerCase(/\./g, '');

    /*
     * Checks a given slug in a list and if found, increments count and recursively checks again
     */
    const slugSuggestionHelper = (slugToCheck, slugList, count) => {
      const slug = count > 0 ? `${slugToCheck}${count}` : slugToCheck;
      if (slugList.indexOf(slug) === -1) {
        return slug;
      } else {
        return slugSuggestionHelper(`${slugToCheck}`, slugList, count + 1);
      }
    };

    // fetch any matching slugs or slugs for the top choice in the list above
    return Sequelize.query(
      `
        SELECT slug FROM "Updates" WHERE "CollectiveId"=${this.CollectiveId} AND slug like '${suggestion}%'
      `,
      {
        type: Sequelize.QueryTypes.SELECT,
      },
    )
      .then(updateObjectList => updateObjectList.map(update => update.slug))
      .then(slugList => slugSuggestionHelper(suggestion, slugList, 0))
      .then(slug => {
        if (!slug) return Promise.reject(new Error("We couldn't generate a unique slug for this Update"));
        this.slug = slug;
      });
  };

  Update.createMany = (updates, defaultValues) => {
    return Promise.map(updates, u => Update.create(defaults({}, u, defaultValues)), { concurrency: 1 }).catch(
      console.error,
    );
  };

  Update.findBySlug = (slug, options = {}) => {
    if (!slug || slug.length < 1) {
      return Promise.resolve(null);
    }
    return Update.findOne({
      where: { slug: slug.toLowerCase() },
      ...options,
    }).then(Update => {
      if (!Update) {
        throw new Error(`No update found with slug ${slug}`);
      }
      return Update;
    });
  };

  Update.associate = m => {
    Update.belongsTo(m.Collective, {
      foreignKey: 'CollectiveId',
      as: 'collective',
    });
    Update.belongsTo(m.Collective, {
      foreignKey: 'FromCollectiveId',
      as: 'fromCollective',
    });
    Update.belongsTo(m.Tier, { foreignKey: 'TierId', as: 'tier' });
    Update.belongsTo(m.User, { foreignKey: 'LastEditedByUserId', as: 'user' });
  };

  Historical(Update, Sequelize);

  return Update;
}
<commit_msg>model(updates): add 'isPrivate' field to editable attributes<commit_after>/**
 * Dependencies.
 */
import config from 'config';
import Historical from 'sequelize-historical';
import slugify from 'limax';
import Promise from 'bluebird';
import showdown from 'showdown';
import { defaults, pick } from 'lodash';

import * as errors from '../graphql/errors';
import activities from '../constants/activities';
import { sanitizeObject } from '../lib/utils';
import { mustHaveRole } from '../lib/auth';

const markdownConverter = new showdown.Converter();

/**
 * Update Model.
 */
export default function(Sequelize, DataTypes) {
  const { models } = Sequelize;

  const Update = Sequelize.define(
    'Update',
    {
      id: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
      },

      slug: {
        type: DataTypes.STRING,
        unique: true,
        allowNull: false,
        set(slug) {
          if (slug && slug.toLowerCase) {
            this.setDataValue(
              'slug',
              slug
                .toLowerCase()
                .replace(/ /g, '-')
                .replace(/\./g, ''),
            );
          }
        },
      },

      CollectiveId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Collectives',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: false,
      },

      TierId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Tiers',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true,
      },

      FromCollectiveId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Collectives',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true,
      },

      CreatedByUserId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Users',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true, // non authenticated users can create a Update
      },

      LastEditedByUserId: {
        type: DataTypes.INTEGER,
        references: {
          model: 'Users',
          key: 'id',
        },
        onDelete: 'SET NULL',
        onUpdate: 'CASCADE',
        allowNull: true, // needs to be true because of old rows
      },

      title: {
        type: DataTypes.STRING,
        validate: {
          len: [1, 255],
        },
      },

      markdown: DataTypes.TEXT,
      html: {
        type: DataTypes.TEXT,
        get() {
          return this.getDataValue('markdown')
            ? markdownConverter.makeHtml(this.getDataValue('markdown'))
            : this.getDataValue('html');
        },
      },

      image: DataTypes.STRING,

      isPrivate: {
        type: DataTypes.BOOLEAN,
        defaultValue: false,
      },

      tags: {
        type: DataTypes.ARRAY(DataTypes.STRING),
      },

      publishedAt: {
        type: DataTypes.DATE,
      },

      createdAt: {
        type: DataTypes.DATE,
        defaultValue: Sequelize.NOW,
      },

      updatedAt: {
        type: DataTypes.DATE,
        defaultValue: Sequelize.NOW,
      },

      deletedAt: {
        type: DataTypes.DATE,
      },
    },
    {
      paranoid: true,

      getterMethods: {
        // Info.
        info() {
          return {
            id: this.id,
            title: this.title,
            html: this.html,
            image: this.image,
            createdAt: this.createdAt,
            updatedAt: this.updatedAt,
            publishedAt: this.publishedAt,
            slug: this.slug,
            tags: this.tags,
          };
        },
        minimal() {
          return {
            id: this.id,
            publishedAt: this.publishedAt,
            title: this.title,
            image: this.image,
            slug: this.slug,
          };
        },
        activity() {
          return {
            id: this.id,
            slug: this.slug,
            title: this.title,
            CollectiveId: this.CollectiveId,
            FromCollectiveId: this.FromCollectiveId,
            TierId: this.TierId,
          };
        },
      },

      hooks: {
        beforeValidate: instance => {
          if (!instance.publishedAt || !instance.slug) return instance.generateSlug();
        },
        beforeUpdate: instance => {
          if (!instance.publishedAt || !instance.slug) return instance.generateSlug();
        },
        afterCreate: instance => {
          models.Activity.create({
            type: activities.COLLECTIVE_UPDATE_CREATED,
            UserId: instance.LastEditedByUserId,
            CollectiveId: instance.CollectiveId,
            data: {
              update: instance.activity,
            },
          });
        },
      },
    },
  );

  /**
   * Instance Methods
   */

  // Edit an update
  Update.prototype.edit = async function(remoteUser, newUpdateData) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'edit this update');
    if (newUpdateData.TierId) {
      const tier = await models.Tier.findByPk(newUpdateData.TierId);
      if (!tier) {
        throw new errors.ValidationFailed({ message: 'Tier not found' });
      }
      if (tier.CollectiveId !== this.CollectiveId) {
        throw new errors.ValidationFailed({
          message: "Cannot link this update to a Tier that doesn't belong to this collective",
        });
      }
    }
    const editableAttributes = [
      'TierId',
      'FromCollectiveId',
      'title',
      'html',
      'markdown',
      'image',
      'tags',
      'isPrivate',
    ];
    sanitizeObject(newUpdateData, ['html', 'markdown']);
    return await this.update({
      ...pick(newUpdateData, editableAttributes),
      LastEditedByUserId: remoteUser.id,
    });
  };

  // Publish update
  Update.prototype.publish = async function(remoteUser) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'publish this update');
    this.publishedAt = new Date();
    this.collective = this.collective || (await models.Collective.findByPk(this.CollectiveId));
    models.Activity.create({
      type: activities.COLLECTIVE_UPDATE_PUBLISHED,
      UserId: remoteUser.id,
      CollectiveId: this.CollectiveId,
      data: {
        collective: this.collective.activity,
        update: this.activity,
        url: `${config.host.website}/${this.collective.slug}/updates/${this.slug}`,
      },
    });
    return await this.save();
  };

  // Unpublish update
  Update.prototype.unpublish = async function(remoteUser) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'unpublish this update');
    this.publishedAt = null;
    return await this.save();
  };

  Update.prototype.delete = async function(remoteUser) {
    mustHaveRole(remoteUser, 'ADMIN', this.CollectiveId, 'delete this update');
    return this.destroy();
  };

  // Returns the User model of the User that created this Update
  Update.prototype.getUser = function() {
    return models.User.findByPk(this.CreatedByUserId);
  };

  /*
   * If there is a username suggested, we'll check that it's valid or increase it's count
   * Otherwise, we'll suggest something.
   */
  Update.prototype.generateSlug = function() {
    if (!this.title) return;
    const suggestion = slugify(this.title.trim()).toLowerCase(/\./g, '');

    /*
     * Checks a given slug in a list and if found, increments count and recursively checks again
     */
    const slugSuggestionHelper = (slugToCheck, slugList, count) => {
      const slug = count > 0 ? `${slugToCheck}${count}` : slugToCheck;
      if (slugList.indexOf(slug) === -1) {
        return slug;
      } else {
        return slugSuggestionHelper(`${slugToCheck}`, slugList, count + 1);
      }
    };

    // fetch any matching slugs or slugs for the top choice in the list above
    return Sequelize.query(
      `
        SELECT slug FROM "Updates" WHERE "CollectiveId"=${this.CollectiveId} AND slug like '${suggestion}%'
      `,
      {
        type: Sequelize.QueryTypes.SELECT,
      },
    )
      .then(updateObjectList => updateObjectList.map(update => update.slug))
      .then(slugList => slugSuggestionHelper(suggestion, slugList, 0))
      .then(slug => {
        if (!slug) return Promise.reject(new Error("We couldn't generate a unique slug for this Update"));
        this.slug = slug;
      });
  };

  Update.createMany = (updates, defaultValues) => {
    return Promise.map(updates, u => Update.create(defaults({}, u, defaultValues)), { concurrency: 1 }).catch(
      console.error,
    );
  };

  Update.findBySlug = (slug, options = {}) => {
    if (!slug || slug.length < 1) {
      return Promise.resolve(null);
    }
    return Update.findOne({
      where: { slug: slug.toLowerCase() },
      ...options,
    }).then(Update => {
      if (!Update) {
        throw new Error(`No update found with slug ${slug}`);
      }
      return Update;
    });
  };

  Update.associate = m => {
    Update.belongsTo(m.Collective, {
      foreignKey: 'CollectiveId',
      as: 'collective',
    });
    Update.belongsTo(m.Collective, {
      foreignKey: 'FromCollectiveId',
      as: 'fromCollective',
    });
    Update.belongsTo(m.Tier, { foreignKey: 'TierId', as: 'tier' });
    Update.belongsTo(m.User, { foreignKey: 'LastEditedByUserId', as: 'user' });
  };

  Historical(Update, Sequelize);

  return Update;
}
<|endoftext|>


<commit_before>const connectToFirebase = () => {
    const admin = require("firebase-admin");
    let serviceAccount = require("./config/quizchatbot-ce222-firebase-adminsdk.json")
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://quizchatbot-ce222.firebaseio.com/"
    })
    return admin
}
const admin = connectToFirebase()

//get total number of questions
const getNumberOfQuestions = async () => {
    let keys = await getAllQuestionKeys()
    let numberOfQuestions = keys.length
    return numberOfQuestions
}

//get all questions from firebase
const getQuestionsFromFirebase = async () => {
    // Get a database reference to our posts
    let db = admin.database()
    let ref = db.ref("/Quests")

    let questionSnapshots
    // Attach an asynchronous callback to read the data at our posts reference
    const result = await new Promise(function (resolve, reject) {
        ref.on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return errorObject.code
    })

    return result
}

const getAllAnswersFromQuestion = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).child("answers").on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    //console.log('from promise', result)
    return result
}

const getQuestionFromId = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    return result
}

const getAllQuestionKeys = () => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Quests")

    ref.orderByKey().once("value", (snapshot) => {
        let keys = Object.keys(snapshot.val())
        console.log("keys in getAllQuestionKeys =  " + keys)
        resolve(keys)
    }, (errorObject) => {
        console.log("Cannot get keys = " + errorObject.code)
    })

})

//get key of questions already done by that user
//query only question that done in that round
const getQuestionDone = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                keysDone.push(resultSnapshot[property].question)
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const getQuestionTest = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        console.log("resultSnapshot = ", resultSnapshot)
        for (let property in resultSnapshot) {
            console.log("property = ", property)
            if (resultSnapshot.hasOwnProperty(property)) {
                keysDone.push(resultSnapshot[property].question)
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const saveResultToFirebase = async (senderID, prepareResult) => {
    let result = prepareResult[0]
    let keyQuestion = result.question
    console.log("key = ", keyQuestion)
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("results").push({
        "answer": result.answer,
        "doneAt": result.doneAt,
        "startedAt": result.startedAt,
        "duration": result.duration,
        "point": result.point,
        "question": result.question,
        "result": result.result,
        "round" : result.round,
        "score" : result.score
    })
}

const saveUserToFirebase = (senderID, user) => {
    console.log("User in firebase= ", user)
    let db = admin.database()
    let ref = db.ref("/Developer/")
    let hasUser = false
    //check if firebase has that user data
    ref.once("value")
        .then((snapshot) => {
            snapshot.forEach((childSnapshot) => {
                console.log("chilssnapshot = ", childSnapshot.key)
                if (childSnapshot.key == senderID) {
                    console.log("Already have user information")
                    hasUser = true
                    return
                }
            });
        });

    //if firebase doesn't have user data
    ref = db.ref("/Developer/" + senderID)
    ref.update({ profile: user })
}

const saveSummaryToFirebase = (senderID, summary) => {
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("summary").child(summary.round).update({
        "round": summary.round,
        "done": summary.done,
        "keysQuestionLeft": summary.keysQuestionLeft,
        "skill": summary.skill,
        "grade": summary.grade,
        "score": summary.score,
        "totalScore" : summary.totalScore
    })
}

module.exports = {
    connectToFirebase, getQuestionsFromFirebase, getAllAnswersFromQuestion, getQuestionFromId,
    getAllQuestionKeys, saveResultToFirebase, saveUserToFirebase, saveSummaryToFirebase, getNumberOfQuestions, getQuestionDone,
    getQuestionTest
}

<commit_msg>test firebase<commit_after>const connectToFirebase = () => {
    const admin = require("firebase-admin");
    let serviceAccount = require("./config/quizchatbot-ce222-firebase-adminsdk.json")
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://quizchatbot-ce222.firebaseio.com/"
    })
    return admin
}
const admin = connectToFirebase()

//get total number of questions
const getNumberOfQuestions = async () => {
    let keys = await getAllQuestionKeys()
    let numberOfQuestions = keys.length
    return numberOfQuestions
}

//get all questions from firebase
const getQuestionsFromFirebase = async () => {
    // Get a database reference to our posts
    let db = admin.database()
    let ref = db.ref("/Quests")

    let questionSnapshots
    // Attach an asynchronous callback to read the data at our posts reference
    const result = await new Promise(function (resolve, reject) {
        ref.on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return errorObject.code
    })

    return result
}

const getAllAnswersFromQuestion = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).child("answers").on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    //console.log('from promise', result)
    return result
}

const getQuestionFromId = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    return result
}

const getAllQuestionKeys = () => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Quests")

    ref.orderByKey().once("value", (snapshot) => {
        let keys = Object.keys(snapshot.val())
        console.log("keys in getAllQuestionKeys =  " + keys)
        resolve(keys)
    }, (errorObject) => {
        console.log("Cannot get keys = " + errorObject.code)
    })

})

//get key of questions already done by that user
//query only question that done in that round
const getQuestionDone = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                if (resultSnapshot[property].round == round) {
                    keysDone.push(resultSnapshot[property].question)
                }
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const getQuestionTest = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        console.log("resultSnapshot = ", resultSnapshot)
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                if (resultSnapshot[property].round == round) {
                    keysDone.push(resultSnapshot[property].question)
                }
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const saveResultToFirebase = async (senderID, prepareResult) => {
    let result = prepareResult[0]
    let keyQuestion = result.question
    console.log("key = ", keyQuestion)
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("results").push({
        "answer": result.answer,
        "doneAt": result.doneAt,
        "startedAt": result.startedAt,
        "duration": result.duration,
        "point": result.point,
        "question": result.question,
        "result": result.result,
        "round": result.round,
        "score": result.score
    })
}

const saveUserToFirebase = (senderID, user) => {
    console.log("User in firebase= ", user)
    let db = admin.database()
    let ref = db.ref("/Developer/")
    let hasUser = false
    //check if firebase has that user data
    ref.once("value")
        .then((snapshot) => {
            snapshot.forEach((childSnapshot) => {
                console.log("chilssnapshot = ", childSnapshot.key)
                if (childSnapshot.key == senderID) {
                    console.log("Already have user information")
                    hasUser = true
                    return
                }
            });
        });

    //if firebase doesn't have user data
    ref = db.ref("/Developer/" + senderID)
    ref.update({ profile: user })
}

const saveSummaryToFirebase = (senderID, summary) => {
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("summary").child(summary.round).update({
        "round": summary.round,
        "done": summary.done,
        "keysQuestionLeft": summary.keysQuestionLeft,
        "skill": summary.skill,
        "grade": summary.grade,
        "score": summary.score,
        "totalScore": summary.totalScore
    })
}

module.exports = {
    connectToFirebase, getQuestionsFromFirebase, getAllAnswersFromQuestion, getQuestionFromId,
    getAllQuestionKeys, saveResultToFirebase, saveUserToFirebase, saveSummaryToFirebase, getNumberOfQuestions, getQuestionDone,
    getQuestionTest
}

<|endoftext|>


<commit_before>const connectToFirebase = () => {
    const admin = require("firebase-admin");
    let serviceAccount = require("./config/quizchatbot-ce222-firebase-adminsdk.json")
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://quizchatbot-ce222.firebaseio.com/"
    })
    return admin
}
const admin = connectToFirebase()

//get total number of questions
const getNumberOfQuestions = async () => {
    let keys = await getAllQuestionKeys()
    let numberOfQuestions = keys.length
    return numberOfQuestions
}

//get all questions from firebase
const getQuestionsFromFirebase = async () => {
    // Get a database reference to our posts
    let db = admin.database()
    let ref = db.ref("/Quests")

    let questionSnapshots
    // Attach an asynchronous callback to read the data at our posts reference
    const result = await new Promise(function (resolve, reject) {
        ref.on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return errorObject.code
    })

    return result
}

const getAllAnswersFromQuestion = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).child("answers").on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    //console.log('from promise', result)
    return result
}

const getQuestionFromId = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    return result
}

const getAllQuestionKeys = () => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Quests")

    ref.orderByKey().once("value", (snapshot) => {
        let keys = Object.keys(snapshot.val())
        console.log("keys in getAllQuestionKeys =  " + keys)
        resolve(keys)
    }, (errorObject) => {
        console.log("Cannot get keys = " + errorObject.code)
    })

})

//get key of questions already done by that user
//query only question that done in that round
const getQuestionDone = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                keysDone.push(resultSnapshot[property].question)
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const getQuestionTest = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        console.log("snapshot = ", snapshot)
        console.log("resultSnapshot = ", resultSnapshot)
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                keysDone.push(resultSnapshot[property].question)
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const saveResultToFirebase = async (senderID, prepareResult) => {
    let result = prepareResult[0]
    let keyQuestion = result.question
    console.log("key = ", keyQuestion)
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("results").push({
        "answer": result.answer,
        "doneAt": result.doneAt,
        "startedAt": result.startedAt,
        "duration": result.duration,
        "point": result.point,
        "question": result.question,
        "result": result.result,
        "round" : result.round,
        "score" : result.score
    })
}

const saveUserToFirebase = (senderID, user) => {
    console.log("User in firebase= ", user)
    let db = admin.database()
    let ref = db.ref("/Developer/")
    let hasUser = false
    //check if firebase has that user data
    ref.once("value")
        .then((snapshot) => {
            snapshot.forEach((childSnapshot) => {
                console.log("chilssnapshot = ", childSnapshot.key)
                if (childSnapshot.key == senderID) {
                    console.log("Already have user information")
                    hasUser = true
                    return
                }
            });
        });

    //if firebase doesn't have user data
    ref = db.ref("/Developer/" + senderID)
    ref.update({ profile: user })
}

const saveSummaryToFirebase = (senderID, summary) => {
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("summary").child(summary.round).update({
        "round": summary.round,
        "done": summary.done,
        "keysQuestionLeft": summary.keysQuestionLeft,
        "skill": summary.skill,
        "grade": summary.grade,
        "score": summary.score,
        "totalScore" : summary.totalScore
    })
}

module.exports = {
    connectToFirebase, getQuestionsFromFirebase, getAllAnswersFromQuestion, getQuestionFromId,
    getAllQuestionKeys, saveResultToFirebase, saveUserToFirebase, saveSummaryToFirebase, getNumberOfQuestions, getQuestionDone,
    getQuestionTest
}

<commit_msg>test firebase<commit_after>const connectToFirebase = () => {
    const admin = require("firebase-admin");
    let serviceAccount = require("./config/quizchatbot-ce222-firebase-adminsdk.json")
    admin.initializeApp({
        credential: admin.credential.cert(serviceAccount),
        databaseURL: "https://quizchatbot-ce222.firebaseio.com/"
    })
    return admin
}
const admin = connectToFirebase()

//get total number of questions
const getNumberOfQuestions = async () => {
    let keys = await getAllQuestionKeys()
    let numberOfQuestions = keys.length
    return numberOfQuestions
}

//get all questions from firebase
const getQuestionsFromFirebase = async () => {
    // Get a database reference to our posts
    let db = admin.database()
    let ref = db.ref("/Quests")

    let questionSnapshots
    // Attach an asynchronous callback to read the data at our posts reference
    const result = await new Promise(function (resolve, reject) {
        ref.on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then((questionSnapshots) => {
        return questionSnapshots
    }).catch((errorObject) => {
        return errorObject.code
    })

    return result
}

const getAllAnswersFromQuestion = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).child("answers").on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    //console.log('from promise', result)
    return result
}

const getQuestionFromId = async (id) => {
    var db = admin.database()
    var ref = db.ref("/Quests")

    const result = await new Promise(function (resolve, reject) {
        ref.child(id).on("value", (snapshot) => {
            questionSnapshots = snapshot.val()
            resolve(questionSnapshots)
        }, (errorObject) => {
            reject(errorObject)
            console.log("The read failed: " + errorObject.code)
        })
    }).then(function (questionSnapshots) {
        return questionSnapshots
    }).catch(function (errorObject) {
        return "The read failed: " + errorObject.code
    })

    return result
}

const getAllQuestionKeys = () => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Quests")

    ref.orderByKey().once("value", (snapshot) => {
        let keys = Object.keys(snapshot.val())
        console.log("keys in getAllQuestionKeys =  " + keys)
        resolve(keys)
    }, (errorObject) => {
        console.log("Cannot get keys = " + errorObject.code)
    })

})

//get key of questions already done by that user
//query only question that done in that round
const getQuestionDone = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                keysDone.push(resultSnapshot[property].question)
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const getQuestionTest = async (senderID, round) => new Promise(async (resolve) => {
    const db = admin.database()
    const ref = db.ref("/Developer/" + senderID)
    let keysDone = []
    ref.child("results").on("value", (snapshot) => {
        let resultSnapshot = snapshot.val()
        console.log("resultSnapshot = ", resultSnapshot.val())
        for (let property in resultSnapshot) {
            if (resultSnapshot.hasOwnProperty(property)) {
                keysDone.push(resultSnapshot[property].question)
            }
        }
        resolve(keysDone)
    }, (errorObject) => {
        console.log("Cannot get keys of questions that user already done  = " + errorObject.code)

    })

})

const saveResultToFirebase = async (senderID, prepareResult) => {
    let result = prepareResult[0]
    let keyQuestion = result.question
    console.log("key = ", keyQuestion)
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("results").push({
        "answer": result.answer,
        "doneAt": result.doneAt,
        "startedAt": result.startedAt,
        "duration": result.duration,
        "point": result.point,
        "question": result.question,
        "result": result.result,
        "round" : result.round,
        "score" : result.score
    })
}

const saveUserToFirebase = (senderID, user) => {
    console.log("User in firebase= ", user)
    let db = admin.database()
    let ref = db.ref("/Developer/")
    let hasUser = false
    //check if firebase has that user data
    ref.once("value")
        .then((snapshot) => {
            snapshot.forEach((childSnapshot) => {
                console.log("chilssnapshot = ", childSnapshot.key)
                if (childSnapshot.key == senderID) {
                    console.log("Already have user information")
                    hasUser = true
                    return
                }
            });
        });

    //if firebase doesn't have user data
    ref = db.ref("/Developer/" + senderID)
    ref.update({ profile: user })
}

const saveSummaryToFirebase = (senderID, summary) => {
    let db = admin.database()
    let ref = db.ref("/Developer/" + senderID)
    ref.child("summary").child(summary.round).update({
        "round": summary.round,
        "done": summary.done,
        "keysQuestionLeft": summary.keysQuestionLeft,
        "skill": summary.skill,
        "grade": summary.grade,
        "score": summary.score,
        "totalScore" : summary.totalScore
    })
}

module.exports = {
    connectToFirebase, getQuestionsFromFirebase, getAllAnswersFromQuestion, getQuestionFromId,
    getAllQuestionKeys, saveResultToFirebase, saveUserToFirebase, saveSummaryToFirebase, getNumberOfQuestions, getQuestionDone,
    getQuestionTest
}

<|endoftext|>


<commit_before>'use strict';

/* App Module */

//App Module
var myApp = angular.module('myApp', ['ngRoute','ngResource','ngMaterial','ngMessages']).
config(function($mdThemingProvider) {
  $mdThemingProvider.definePalette('amazingPaletteName', {
    '50': 'E0F7FA',
    '100': 'B2EBF2',
    '200': '80DEEA',
    '300': '4DD0E1',
    '400': '26C6DA',
    '500': '00BCD4',
    '600': '00ACC1',
    '700': '0097A7',
    '800': '00838F',
    '900': '006064',
    'A100': '84FFFF',
    'A200': '18FFFF',
    'A400': '00E5FF',
    'A700': '00B8D4',
    'contrastDefaultColor': 'light',    // whether, by default, text (contrast)
                                        // on this palette should be dark or light
    'contrastDarkColors': ['50', '100', //hues which contrast should be 'dark' by default
     '200', '300', '400', 'A100'],
    'contrastLightColors': undefined    // could also specify this if default was 'dark'
  });
  $mdThemingProvider.theme('default')
    .primaryPalette('amazingPaletteName')
});

//Set up routing
myApp.config(['$routeProvider',
	function($routeProvider) {
		$routeProvider.
			when('/index',{
				templateUrl: 'assets/partials/index.html'
			}).
			when('/login',{
				templateUrl: 'assets/partials/login.html'
			}).
			when('/bestiary/view/:bestiaryId',{
				templateUrl: 'assets/partials/bestiary/view.html',
				controller: 'bestiaryCtrl',
				resolve: bestiaryCtrl.resolve
			}).
			when('/bestiary/list',{
				templateUrl: 'assets/partials/bestiary/list.html',
				controller: 'bestiaryCtrl'
			}).
			when('/creature/view/:creatureId',{
				templateUrl: 'assets/partials/creature/view.html',
				controller: 'creatureCtrl',
				resolve: creatureCtrl.resolve
			}).
			when('/creature/create',{
				templateUrl: 'assets/partials/creature/create.html',
				controller: 'creatureCtrl',
				resolve: creatureCtrl.resolve
			}).
			otherwise({
				redirectTo: '/index'
			});
	}]);
<commit_msg>added update route to front end, sharing the same html as create page. it is fully functional but ugly.<commit_after>'use strict';

/* App Module */

//App Module
var myApp = angular.module('myApp', ['ngRoute','ngResource','ngMaterial','ngMessages']).
config(function($mdThemingProvider) {
  $mdThemingProvider.definePalette('amazingPaletteName', {
    '50': 'E0F7FA',
    '100': 'B2EBF2',
    '200': '80DEEA',
    '300': '4DD0E1',
    '400': '26C6DA',
    '500': '00BCD4',
    '600': '00ACC1',
    '700': '0097A7',
    '800': '00838F',
    '900': '006064',
    'A100': '84FFFF',
    'A200': '18FFFF',
    'A400': '00E5FF',
    'A700': '00B8D4',
    'contrastDefaultColor': 'light',    // whether, by default, text (contrast)
                                        // on this palette should be dark or light
    'contrastDarkColors': ['50', '100', //hues which contrast should be 'dark' by default
     '200', '300', '400', 'A100'],
    'contrastLightColors': undefined    // could also specify this if default was 'dark'
  });
  $mdThemingProvider.theme('default')
    .primaryPalette('amazingPaletteName')
});

//Set up routing
myApp.config(['$routeProvider',
	function($routeProvider) {
		$routeProvider.
			when('/index',{
				templateUrl: 'assets/partials/index.html'
			}).
			when('/login',{
				templateUrl: 'assets/partials/login.html'
			}).
			when('/bestiary/view/:bestiaryId',{
				templateUrl: 'assets/partials/bestiary/view.html',
				controller: 'bestiaryCtrl',
				resolve: bestiaryCtrl.resolve
			}).
			when('/bestiary/list',{
				templateUrl: 'assets/partials/bestiary/list.html',
				controller: 'bestiaryCtrl'
			}).
			when('/creature/view/:creatureId',{
				templateUrl: 'assets/partials/creature/view.html',
				controller: 'creatureCtrl',
				resolve: creatureCtrl.resolve
			}).
			when('/creature/edit/:creatureId',{
				templateUrl: 'assets/partials/creature/create.html',
				controller: 'creatureCtrl',
				resolve: creatureCtrl.resolve
			}).
			when('/creature/create',{
				templateUrl: 'assets/partials/creature/create.html',
				controller: 'creatureCtrl',
				resolve: creatureCtrl.resolve
			}).
			otherwise({
				redirectTo: '/index'
			});
	}]);
<|endoftext|>


<commit_before>/**
 * Created by chrisng on 2/22/17.
 */

const request = require('request');
const cheerio = require('cheerio');
const snoowrap = require('snoowrap');

const findLink = (url) => {
  request(url, (err, res, body) => {
    const $ = cheerio.load(res.body);
    const linkElem = $('.linklisting .usertext-body .md a')[0];
    if (linkElem) {
      return linkElem.attribs.href;
    }
    return null;
  });
};

const handlePost = (post) => {
  let link;
  if (post.url === `https://www.reddit.com${post.permalink}`) {
    link = findLink(post.url);
  }
  if (!link) {
    return;
  }

  // if brand name exists in url
  // insert into db
  // else
  // scrape site to see if exists in brand
};

const grabLatestFmfArticles = () => {
  const r = new snoowrap({
    userAgent: 'chris',
    clientId: process.env.REDDIT_CLIENT_ID,
    clientSecret: process.env.REDDIT_CLIENT_SECRET,
    refreshToken: process.env.REDDIT_REFRESH_TOKEN,
  });

  r.getSubreddit('frugalmalefashion')
    .getNew({limit: 100})
    .forEach((post) => {
      const updatedPost = {
        id: post.id,
        title: post.title,
        url: post.url,
        permalink: post.permalink,
        createdUtc: post.created_utc,
      };
      handlePost(updatedPost);
    });
};

grabLatestFmfArticles();

module.exports = { grabLatestFmfArticles };
<commit_msg>partially done reddit scripts<commit_after>/**
 * Created by chrisng on 2/22/17.
 */

const request = require('request');
const cheerio = require('cheerio');
const snoowrap = require('snoowrap');

const findLink = (url) => {
  request(url, (err, res, body) => {
    const $ = cheerio.load(res.body);
    const linkElem = $('.linklisting .usertext-body .md a')[0];
    if (linkElem) {
      return linkElem.attribs.href;
    }
    return null;
  });
};

const handlePost = (post) => {
  let link;
  if (post.url === `https://www.reddit.com${post.permalink}`) {
    link = findLink(post.url);
  }
  if (!link) {
    return;
  }

  // if brand name exists in url
  // insert into db
  // else
  // scrape site to see if exists in brand
};

const grabLatestFmfArticles = () => {
  const r = new snoowrap({
    userAgent: 'chris',
    clientId: process.env.REDDIT_CLIENT_ID,
    clientSecret: process.env.REDDIT_CLIENT_SECRET,
    refreshToken: process.env.REDDIT_REFRESH_TOKEN,
  });

  r.getSubreddit('frugalmalefashion')
    .getNew({limit: 100})
    .forEach((post) => {
      // add clause to skip if date is past latest grab date
      const updatedPost = {
        id: post.id,
        title: post.title,
        url: post.url,
        permalink: post.permalink,
        createdUtc: post.created_utc,
      };
      handlePost(updatedPost);
    });
};

grabLatestFmfArticles();

module.exports = { grabLatestFmfArticles };
<|endoftext|>


<commit_before>/* eslint-disable no-console */

import express from 'express';
import path from 'path';
import webpack from 'webpack';
import config from '../webpack.config';

const app = express();
const port = 3000;
const compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));

app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '../index.html'));
});

app.listen(port, (err) => {
  if (err) {
    console.log('Error: ', err);
  }
  console.log(`> Diffy.js Demo server is running on: http://localhost:${port}`);
})
<commit_msg>Fix typo<commit_after>/* eslint-disable no-console */

import express from 'express';
import path from 'path';
import webpack from 'webpack';
import config from '../webpack.config';

const app = express();
const port = 3000;
const compiler = webpack(config);

app.use(require('webpack-dev-middleware')(compiler, {
  noInfo: true,
  publicPath: config.output.publicPath
}));

app.use(require('webpack-hot-middleware')(compiler));

app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, '../index.html'));
});

app.listen(port, (err) => {
  if (err) {
    console.log('Error: ', err);
  }
  console.log(`> Diffy.js Dev server is running on: http://localhost:${port}`);
})
<|endoftext|>