<commit_before>/**
 *
 * syncthing adapter
 *
 *
 * ioBroker Adapter to load meta data of a folder of your Syncthing server.
 * The adapter loads all 5min (default) the amount of bytes of the global folder (the data within the cloud), of your local folder and the state of the folder (e.g. idle).
 * Additionally it reformates the bytes to a more readable string (e.g. '3.376 KB' instead of '2433') besides the original value.
 *
 * An API Key of the Syncthing installation is necessary to use this adapter to load the data of your Syncthing folder.
 * To find it load your Syncthing admin overview (typically the IP of your syncthing installation on port 8080) and go to 'Actions' -> 'Advanced'. Make sure you don't share your API key.
 * The Folder ID of your Syncthing folder can be found in the Syncthing admin overview when you expand the Folder on the main overview.
 * You'll find 'Folder ID' below the expanded folder.
 *
 */

/* jshint -W097 */// jshint strict:false
/*jslint node: true */
"use strict";

// you have to require the utils module and call adapter function
var utils =    require(__dirname + '/lib/utils'); // Get common adapter utils

// you have to call the adapter function and pass a options object
// name has to be set and has to be equal to adapters folder name and main file name excluding extension
// adapter will be restarted automatically every time as the configuration changed, e.g system.adapter.syncthing.0
var adapter = utils.Adapter('syncthing');

/*
* Global Variables to be used across functions
*/
var endpoint_DBStatus = "/rest/db/status";                    // Provides major folder data. See: https://docs.syncthing.net/rest/db-status-get.html
var endpoint_SystemStatus = "/rest/db/completion";            // Provides completion percentage. See: https://docs.syncthing.net/rest/db-completion-get.html
var xmlHttp = null;

// is called when adapter shuts down - callback has to be called under any circumstances!
adapter.on('unload', function (callback) {
    try {
        adapter.log.info('cleaned everything up...');
        callback();
    } catch (e) {
        callback();
    }
});

// is called if a subscribed object changes
/*
adapter.on('objectChange', function (id, obj) {
    // Warning, obj can be null if it was deleted
    adapter.log.info('objectChange ' + id + ' ' + JSON.stringify(obj));
});
*/

// is called if a subscribed state changes
/*
adapter.on('stateChange', function (id, state) {
    // Warning, state can be null if it was deleted
    adapter.log.info('stateChange ' + id + ' ' + JSON.stringify(state));

    // you can use the ack flag to detect if it is status (true) or command (false)
    if (state && !state.ack) {
        adapter.log.info('ack is not set!');
    }
});
*/

// Some message was sent to adapter instance over message box. Used by email, pushover, text2speech, ...
/*
adapter.on('message', function (obj) {
    if (typeof obj == 'object' && obj.message) {
        if (obj.command == 'send') {
            // e.g. send email or pushover or whatever
            console.log('send command');

            // Send response in callback if required
            if (obj.callback) adapter.sendTo(obj.from, obj.command, 'Message received', obj.callback);
        }
    }
});
*/

// is called when databases are connected and adapter received configuration.
// start here!
adapter.on('ready', function () {
    main();
});

function main() {
    // The adapters config (in the instance object everything under the attribute "native") is accessible via
    // adapter.config:
    adapter.log.info('Using config syncthingurl: ' + adapter.config.syncthingurl + ' | syncthingapikey: ' + adapter.config.syncthingapikey + ' | syncthingfolderid: ' + adapter.config.syncthingfolderid);

    /**
    *      For every state in the system there has to be also an object of type state
    *      Here a simple syncthing for a boolean variable named "testVariable"
    *      Because every adapter instance uses its own unique namespace variable names can't collide with other adapters variables
    */
    adapter.setObjectNotExists('folder.globalBytes', {
        type: 'state',
        common: {
            name: 'globalBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.globalBytesFormated', {
        type: 'state',
        common: {
            name: 'globalBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.globalDeleted', {
        type: 'state',
        common: {
            name: 'globalDeleted',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.globalFiles', {
        type: 'state',
        common: {
            name: 'globalFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localBytes', {
        type: 'state',
        common: {
            name: 'localBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localBytesFormated', {
        type: 'state',
        common: {
            name: 'localBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localDeleted', {
        type: 'state',
        common: {
            name: 'localDeleted',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localFiles', {
        type: 'state',
        common: {
            name: 'localFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.inSyncBytes', {
        type: 'state',
        common: {
            name: 'inSyncBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.inSyncBytesFormated', {
        type: 'state',
        common: {
            name: 'inSyncBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.inSyncFiles', {
        type: 'state',
        common: {
            name: 'inSyncFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.needBytes', {
        type: 'state',
        common: {
            name: 'needBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.needBytesFormated', {
        type: 'state',
        common: {
            name: 'needBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.needFiles', {
        type: 'state',
        common: {
            name: 'needFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.ignorePatterns', {
        type: 'state',
        common: {
            name: 'ignorePatterns',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.invalid', {
        type: 'state',
        common: {
            name: 'invalid',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.state', {
        type: 'state',
        common: {
            name: 'state',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.stateChange', {
        type: 'state',
        common: {
            name: 'stateChange',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.version', {
        type: 'state',
        common: {
            name: 'version',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });

    // in this syncthing all states changes inside the adapters namespace are subscribed
    //adapter.subscribeStates('*');

    // START OF SYNCTHING SCRIPTING
    // Update syncthing status
    invokeSyncthingUpdate();
}

/*
* SYNCTHING SPECIFIC FUNCTIONS
*/

function invokeSyncthingUpdate() {
    // Fire API call to syncthing endpoint and update object variables
    httpGetSyncthing();
}

// Invokes HTTP Request
function httpGetSyncthing() {
    // Create full URL of endpoint
    var syncthingURL = adapter.config.syncthingurl + endpoint_DBStatus + "?folder=" + adapter.config.syncthingfolderid;
    // Prepare new request
    const request = require('request-promise')
    const options = {
        method: 'GET',
        uri: syncthingURL,
        json: true,
        headers: {
            'User-Agent': 'ioBroker Request-Promise',
            'Accept': "text/plain",
            'Content-Type': "text/plain",
            'X-API-Key': adapter.config.syncthingapikey
        }
    }
    // Fire request
    request(options)
        .then(function (response) {
            // Request was successful, use the response object at will
            adapter.log.info("Request to " + syncthingURL + " was successfull");
            // Set the adapter output values
            adapter.setState('folder.globalBytes', { val: response.globalBytes, ack: true });
            adapter.setState('folder.globalBytesFormated', { val: formatBytes(response.globalBytes), ack: true });
            adapter.setState('folder.globalDeleted', { val: response.globalDeleted, ack: true });
            adapter.setState('folder.globalFiles', { val: response.globalFiles, ack: true });
            adapter.setState('folder.localBytes', { val: response.localBytes, ack: true });
            adapter.setState('folder.localBytesFormated', { val: formatBytes(response.localBytes), ack: true });
            adapter.setState('folder.localDeleted', { val: response.localDeleted, ack: true });
            adapter.setState('folder.localFiles', { val: response.localFiles, ack: true });
            adapter.setState('folder.inSyncBytes', { val: response.inSyncBytes, ack: true });
            adapter.setState('folder.inSyncBytesFormated', { val: formatBytes(response.inSyncBytes), ack: true });
            adapter.setState('folder.inSyncFiles', { val: response.inSyncFiles, ack: true });
            adapter.setState('folder.needBytes', { val: response.localBytes, ack: true });
            adapter.setState('folder.needBytesFormated', { val: formatBytes(response.needBytes), ack: true });
            adapter.setState('folder.needFiles', { val: response.needFiles, ack: true });
            adapter.setState('folder.ignorePatterns', { val: response.ignorePatterns, ack: true });
            adapter.setState('folder.invalid', { val: response.invalid, ack: true });
            adapter.setState('folder.state', { val: response.state, ack: true });
            adapter.setState('folder.stateChange', { val: response.stateChanged, ack: true });
            adapter.setState('folder.version', { val: response.version, ack: true });
            // Stop adapter after updating all values
            stopAdapter();
        })
        .catch(function (err) {
            // Something bad happened, handle the error
            adapter.log.info("Request to " + syncthingURL + " failed");
            // Set the adapter output values to error
            adapter.setState('folder.globalBytes', { val: '', ack: true });
            adapter.setState('folder.globalBytesFormated', { val: '', ack: true });
            adapter.setState('folder.globalDeleted', { val: '', ack: true });
            adapter.setState('folder.globalFiles', { val: '', ack: true });
            adapter.setState('folder.localBytes', { val: '', ack: true });
            adapter.setState('folder.localBytesFormated', { val: '', ack: true });
            adapter.setState('folder.localDeleted', { val: '', ack: true });
            adapter.setState('folder.localFiles', { val: '', ack: true });
            adapter.setState('folder.inSyncBytes', { val: '', ack: true });
            adapter.setState('folder.inSyncBytesFormated', { val: '', ack: true });
            adapter.setState('folder.inSyncFiles', { val: '', ack: true });
            adapter.setState('folder.needBytes', { val: '', ack: true });
            adapter.setState('folder.needBytesFormated', { val: '', ack: true });
            adapter.setState('folder.needFiles', { val: '', ack: true });
            adapter.setState('folder.ignorePatterns', { val: '', ack: true });
            adapter.setState('folder.invalid', { val: '', ack: true });
            adapter.setState('folder.state', { val: '', ack: true });
            adapter.setState('folder.stateChange', { val: '', ack: true });
            adapter.setState('folder.version', { val: '', ack: true });
            // Stop adapter after updating all values
            stopAdapter();
        }
    )
}

// Stops this adapter
function stopAdapter() {
    // Stop Adapter (immediately)
    setTimeout(function () {
        adapter.stop();
    }, 5000);
}

// Converts byte size unit into proper larger size unit
function formatBytes(bytes) {
    if (bytes < 1024) return bytes + " Bytes";
    else if (bytes < 1048576) return (bytes / 1024).toFixed(3) + " KB";
    else if (bytes < 1073741824) return (bytes / 1048576).toFixed(3) + " MB";
    else return (bytes / 1073741824).toFixed(3) + " GB";
};
<commit_msg>add adapter-core<commit_after>/**
 *
 * syncthing adapter
 *
 *
 * ioBroker Adapter to load meta data of a folder of your Syncthing server.
 * The adapter loads all 5min (default) the amount of bytes of the global folder (the data within the cloud), of your local folder and the state of the folder (e.g. idle).
 * Additionally it reformates the bytes to a more readable string (e.g. '3.376 KB' instead of '2433') besides the original value.
 *
 * An API Key of the Syncthing installation is necessary to use this adapter to load the data of your Syncthing folder.
 * To find it load your Syncthing admin overview (typically the IP of your syncthing installation on port 8080) and go to 'Actions' -> 'Advanced'. Make sure you don't share your API key.
 * The Folder ID of your Syncthing folder can be found in the Syncthing admin overview when you expand the Folder on the main overview.
 * You'll find 'Folder ID' below the expanded folder.
 *
 */

/* jshint -W097 */// jshint strict:false
/*jslint node: true */
"use strict";

// you have to require the utils module and call adapter function
var utils = require('@iobroker/adapter-core'); // Get common adapter utils

// you have to call the adapter function and pass a options object
// name has to be set and has to be equal to adapters folder name and main file name excluding extension
// adapter will be restarted automatically every time as the configuration changed, e.g system.adapter.syncthing.0
var adapter = utils.Adapter('syncthing');

/*
* Global Variables to be used across functions
*/
var endpoint_DBStatus = "/rest/db/status";                    // Provides major folder data. See: https://docs.syncthing.net/rest/db-status-get.html
var endpoint_SystemStatus = "/rest/db/completion";            // Provides completion percentage. See: https://docs.syncthing.net/rest/db-completion-get.html
var xmlHttp = null;

// is called when adapter shuts down - callback has to be called under any circumstances!
adapter.on('unload', function (callback) {
    try {
        adapter.log.info('cleaned everything up...');
        callback();
    } catch (e) {
        callback();
    }
});

// is called if a subscribed object changes
/*
adapter.on('objectChange', function (id, obj) {
    // Warning, obj can be null if it was deleted
    adapter.log.info('objectChange ' + id + ' ' + JSON.stringify(obj));
});
*/

// is called if a subscribed state changes
/*
adapter.on('stateChange', function (id, state) {
    // Warning, state can be null if it was deleted
    adapter.log.info('stateChange ' + id + ' ' + JSON.stringify(state));

    // you can use the ack flag to detect if it is status (true) or command (false)
    if (state && !state.ack) {
        adapter.log.info('ack is not set!');
    }
});
*/

// Some message was sent to adapter instance over message box. Used by email, pushover, text2speech, ...
/*
adapter.on('message', function (obj) {
    if (typeof obj == 'object' && obj.message) {
        if (obj.command == 'send') {
            // e.g. send email or pushover or whatever
            console.log('send command');

            // Send response in callback if required
            if (obj.callback) adapter.sendTo(obj.from, obj.command, 'Message received', obj.callback);
        }
    }
});
*/

// is called when databases are connected and adapter received configuration.
// start here!
adapter.on('ready', function () {
    main();
});

function main() {
    // The adapters config (in the instance object everything under the attribute "native") is accessible via
    // adapter.config:
    adapter.log.info('Using config syncthingurl: ' + adapter.config.syncthingurl + ' | syncthingapikey: ' + adapter.config.syncthingapikey + ' | syncthingfolderid: ' + adapter.config.syncthingfolderid);

    /**
    *      For every state in the system there has to be also an object of type state
    *      Here a simple syncthing for a boolean variable named "testVariable"
    *      Because every adapter instance uses its own unique namespace variable names can't collide with other adapters variables
    */
    adapter.setObjectNotExists('folder.globalBytes', {
        type: 'state',
        common: {
            name: 'globalBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.globalBytesFormated', {
        type: 'state',
        common: {
            name: 'globalBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.globalDeleted', {
        type: 'state',
        common: {
            name: 'globalDeleted',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.globalFiles', {
        type: 'state',
        common: {
            name: 'globalFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localBytes', {
        type: 'state',
        common: {
            name: 'localBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localBytesFormated', {
        type: 'state',
        common: {
            name: 'localBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localDeleted', {
        type: 'state',
        common: {
            name: 'localDeleted',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.localFiles', {
        type: 'state',
        common: {
            name: 'localFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.inSyncBytes', {
        type: 'state',
        common: {
            name: 'inSyncBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.inSyncBytesFormated', {
        type: 'state',
        common: {
            name: 'inSyncBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.inSyncFiles', {
        type: 'state',
        common: {
            name: 'inSyncFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.needBytes', {
        type: 'state',
        common: {
            name: 'needBytes',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.needBytesFormated', {
        type: 'state',
        common: {
            name: 'needBytesFormated',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.needFiles', {
        type: 'state',
        common: {
            name: 'needFiles',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.ignorePatterns', {
        type: 'state',
        common: {
            name: 'ignorePatterns',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.invalid', {
        type: 'state',
        common: {
            name: 'invalid',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.state', {
        type: 'state',
        common: {
            name: 'state',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.stateChange', {
        type: 'state',
        common: {
            name: 'stateChange',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });
    adapter.setObjectNotExists('folder.version', {
        type: 'state',
        common: {
            name: 'version',
            type: 'string',
            role: 'indicator'
        },
        native: {}
    });

    // in this syncthing all states changes inside the adapters namespace are subscribed
    //adapter.subscribeStates('*');

    // START OF SYNCTHING SCRIPTING
    // Update syncthing status
    invokeSyncthingUpdate();
}

/*
* SYNCTHING SPECIFIC FUNCTIONS
*/

function invokeSyncthingUpdate() {
    // Fire API call to syncthing endpoint and update object variables
    httpGetSyncthing();
}

// Invokes HTTP Request
function httpGetSyncthing() {
    // Create full URL of endpoint
    var syncthingURL = adapter.config.syncthingurl + endpoint_DBStatus + "?folder=" + adapter.config.syncthingfolderid;
    // Prepare new request
    const request = require('request-promise')
    const options = {
        method: 'GET',
        uri: syncthingURL,
        json: true,
        headers: {
            'User-Agent': 'ioBroker Request-Promise',
            'Accept': "text/plain",
            'Content-Type': "text/plain",
            'X-API-Key': adapter.config.syncthingapikey
        }
    }
    // Fire request
    request(options)
        .then(function (response) {
            // Request was successful, use the response object at will
            adapter.log.info("Request to " + syncthingURL + " was successfull");
            // Set the adapter output values
            adapter.setState('folder.globalBytes', { val: response.globalBytes, ack: true });
            adapter.setState('folder.globalBytesFormated', { val: formatBytes(response.globalBytes), ack: true });
            adapter.setState('folder.globalDeleted', { val: response.globalDeleted, ack: true });
            adapter.setState('folder.globalFiles', { val: response.globalFiles, ack: true });
            adapter.setState('folder.localBytes', { val: response.localBytes, ack: true });
            adapter.setState('folder.localBytesFormated', { val: formatBytes(response.localBytes), ack: true });
            adapter.setState('folder.localDeleted', { val: response.localDeleted, ack: true });
            adapter.setState('folder.localFiles', { val: response.localFiles, ack: true });
            adapter.setState('folder.inSyncBytes', { val: response.inSyncBytes, ack: true });
            adapter.setState('folder.inSyncBytesFormated', { val: formatBytes(response.inSyncBytes), ack: true });
            adapter.setState('folder.inSyncFiles', { val: response.inSyncFiles, ack: true });
            adapter.setState('folder.needBytes', { val: response.localBytes, ack: true });
            adapter.setState('folder.needBytesFormated', { val: formatBytes(response.needBytes), ack: true });
            adapter.setState('folder.needFiles', { val: response.needFiles, ack: true });
            adapter.setState('folder.ignorePatterns', { val: response.ignorePatterns, ack: true });
            adapter.setState('folder.invalid', { val: response.invalid, ack: true });
            adapter.setState('folder.state', { val: response.state, ack: true });
            adapter.setState('folder.stateChange', { val: response.stateChanged, ack: true });
            adapter.setState('folder.version', { val: response.version, ack: true });
            // Stop adapter after updating all values
            stopAdapter();
        })
        .catch(function (err) {
            // Something bad happened, handle the error
            adapter.log.info("Request to " + syncthingURL + " failed");
            // Set the adapter output values to error
            adapter.setState('folder.globalBytes', { val: '', ack: true });
            adapter.setState('folder.globalBytesFormated', { val: '', ack: true });
            adapter.setState('folder.globalDeleted', { val: '', ack: true });
            adapter.setState('folder.globalFiles', { val: '', ack: true });
            adapter.setState('folder.localBytes', { val: '', ack: true });
            adapter.setState('folder.localBytesFormated', { val: '', ack: true });
            adapter.setState('folder.localDeleted', { val: '', ack: true });
            adapter.setState('folder.localFiles', { val: '', ack: true });
            adapter.setState('folder.inSyncBytes', { val: '', ack: true });
            adapter.setState('folder.inSyncBytesFormated', { val: '', ack: true });
            adapter.setState('folder.inSyncFiles', { val: '', ack: true });
            adapter.setState('folder.needBytes', { val: '', ack: true });
            adapter.setState('folder.needBytesFormated', { val: '', ack: true });
            adapter.setState('folder.needFiles', { val: '', ack: true });
            adapter.setState('folder.ignorePatterns', { val: '', ack: true });
            adapter.setState('folder.invalid', { val: '', ack: true });
            adapter.setState('folder.state', { val: '', ack: true });
            adapter.setState('folder.stateChange', { val: '', ack: true });
            adapter.setState('folder.version', { val: '', ack: true });
            // Stop adapter after updating all values
            stopAdapter();
        }
    )
}

// Stops this adapter
function stopAdapter() {
    // Stop Adapter (immediately)
    setTimeout(function () {
        adapter.stop();
    }, 5000);
}

// Converts byte size unit into proper larger size unit
function formatBytes(bytes) {
    if (bytes < 1024) return bytes + " Bytes";
    else if (bytes < 1048576) return (bytes / 1024).toFixed(3) + " KB";
    else if (bytes < 1073741824) return (bytes / 1048576).toFixed(3) + " MB";
    else return (bytes / 1073741824).toFixed(3) + " GB";
};
<|endoftext|>


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

function nyt (keys) {
    var myKeys = keys;

	var request = function (path, data, callback, args) {
		var options = {
			hostname: 'api.nytimes.com',
			path: path
		}
		var req = http.request(options, function(res) {
			res.setEncoding('utf8');
			var buffer = '';
			res.on('data', function(chunk) {
				buffer += chunk;
			});
			res.on('end', function() {
				callback(buffer);
			});
		});

		req.on('error', function(err) {
			callback(err);
		});

		req.end();
	}

	var get = function (path, callback, args) {
		request(path, undefined, callback, args);
	}
    this.best_sellers = function (args, which, prequery, callback) {
		if (which === 'get' && (typeof prequery.date === 'undefined' || typeof prequery.list_name === 'undefined')) {
			throw new Error('Date and list name required to get bestsellers');
		}

		var sub_api = {'get':'lists/' + prequery.date + '/' + prequery.list_name + '.json',
		'search':'lists.json',
		'history':'lists/best-sellers/history.json',
		'overview':'lists/overview.json',
		'names':'lists/names.json'}

		if (!callback) {
            callback = args;
            args = undefined;
        }
        var version = 'v2/';
        var path = '/svc/books/' + version + sub_api[which] + '?' + querystring.stringify(args) + '&' + 'api-key=' + keys.best_sellers;
        this.get(path, callback, args);
    }

    this.article = {
        get : function (args, callback) {
            if(!callback) {
                callback = args;
                args = undefined;
            }
            var path = '/svc/search/v2/articlesearch.json' +
                '?' + querystring.stringify(args) +
                '&' + 'api-key=' + myKeys['article'];
            get(path, callback, args);
        }
    }

    this.bestSellers = {
        get : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var books = '/svc/books/';
            var date = "";
            if (typeof args.date != undefined) {
                date = args.date;
            }
            var list_name = args['list-name'];
            var args = utils.removeArgs(['date', 'list-name'], args);
            var path = books + version + 'lists/' +
                date + '/' + list_name +
                '.json' + querystring.stringify(args) + '?' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists' + format + '?' + querystring.stringify(args) + '&' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        history : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists/best-sellers/history' + format + '?' + querystring.stringify(args) + '&' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        overview : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists/overview' + format + '?' + querystring.stringify(args) + '&' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        names : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists/names' + format + '?' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        }
    }

    this.community = {
        recent : function (args, callback) {
            if(!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/community/' + version + 'comments/recent' + format + '?force-replies=0' + '&' + querystring.stringify(args) + '&api-key=' + myKeys['community'];
            get(path, callback, args);
        },
        random : function (args, callback) {

        },
        byDate : function (args, callback) {

        },
        byUser : function (args, callback) {

        },
        byURL : function (args, callback) {

        }
    }

    this.districts = {
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args) != '') {
                query = querystring.stringify(args) + '&';
            }
            var path = '/svc/politics/' + version + 'districts' + format + '?' + 'api-key=' + query + myKeys['districts'];
            get(path, callback, args);
        }
    }

    this.eventListings = {
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var path = '/svc/events/' + version + 'listings' + format + '?' + query + 'api-key=' + myKeys['event-listings'];

            get(path, callback, args);
        }
    }

    this.geo = {
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var path = '/svc/semantic/' + version + 'geocodes/query' + format + '?' + query + 'api-key=' + myKeys['geo'];
            get(path, callback, args);
        }
    }

    this.mostPopular = {
        emailed : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var section = args.section;
            var timePeriod = args['time-period'];
            var path = '/svc/mostpopular/' + version + 'mostemailed/' + section +
                '/' + timePeriod + format + '?' + query + 'api-key='+ myKeys['most-popular'];
            get(path, callback, args);
        },
        shared : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var section = args.section;
            var timePeriod = args['time-period'];
            var path = '/svc/mostpopular/' + version + 'mostshared/' + section +
                '/' + timePeriod + format + '?' + query + 'api-key=' + myKeys['most-popular'];
            get(path, callback, args);
        },
        viewed : function (args, callback) {

        }
    }
}

module.exports = nyt;
<commit_msg>added viewed method to most popular api<commit_after>var querystring = require('querystring');
var http = require('http');
var utils = require('./utils');

function nyt (keys) {
    var myKeys = keys;

	var request = function (path, data, callback, args) {
		var options = {
			hostname: 'api.nytimes.com',
			path: path
		}
		var req = http.request(options, function(res) {
			res.setEncoding('utf8');
			var buffer = '';
			res.on('data', function(chunk) {
				buffer += chunk;
			});
			res.on('end', function() {
				callback(buffer);
			});
		});

		req.on('error', function(err) {
			callback(err);
		});

		req.end();
	}

	var get = function (path, callback, args) {
		request(path, undefined, callback, args);
	}
    this.best_sellers = function (args, which, prequery, callback) {
		if (which === 'get' && (typeof prequery.date === 'undefined' || typeof prequery.list_name === 'undefined')) {
			throw new Error('Date and list name required to get bestsellers');
		}

		var sub_api = {'get':'lists/' + prequery.date + '/' + prequery.list_name + '.json',
		'search':'lists.json',
		'history':'lists/best-sellers/history.json',
		'overview':'lists/overview.json',
		'names':'lists/names.json'}

		if (!callback) {
            callback = args;
            args = undefined;
        }
        var version = 'v2/';
        var path = '/svc/books/' + version + sub_api[which] + '?' + querystring.stringify(args) + '&' + 'api-key=' + keys.best_sellers;
        this.get(path, callback, args);
    }

    this.article = {
        get : function (args, callback) {
            if(!callback) {
                callback = args;
                args = undefined;
            }
            var path = '/svc/search/v2/articlesearch.json' +
                '?' + querystring.stringify(args) +
                '&' + 'api-key=' + myKeys['article'];
            get(path, callback, args);
        }
    }

    this.bestSellers = {
        get : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var books = '/svc/books/';
            var date = "";
            if (typeof args.date != undefined) {
                date = args.date;
            }
            var list_name = args['list-name'];
            var args = utils.removeArgs(['date', 'list-name'], args);
            var path = books + version + 'lists/' +
                date + '/' + list_name +
                '.json' + querystring.stringify(args) + '?' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists' + format + '?' + querystring.stringify(args) + '&' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        history : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists/best-sellers/history' + format + '?' + querystring.stringify(args) + '&' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        overview : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists/overview' + format + '?' + querystring.stringify(args) + '&' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        },
        names : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/books/' + version + 'lists/names' + format + '?' + 'api-key=' + myKeys['best-sellers'];
            get(path, callback, args);
        }
    }

    this.community = {
        recent : function (args, callback) {
            if(!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var path = '/svc/community/' + version + 'comments/recent' + format + '?force-replies=0' + '&' + querystring.stringify(args) + '&api-key=' + myKeys['community'];
            get(path, callback, args);
        },
        random : function (args, callback) {

        },
        byDate : function (args, callback) {

        },
        byUser : function (args, callback) {

        },
        byURL : function (args, callback) {

        }
    }

    this.districts = {
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args) != '') {
                query = querystring.stringify(args) + '&';
            }
            var path = '/svc/politics/' + version + 'districts' + format + '?' + 'api-key=' + query + myKeys['districts'];
            get(path, callback, args);
        }
    }

    this.eventListings = {
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var path = '/svc/events/' + version + 'listings' + format + '?' + query + 'api-key=' + myKeys['event-listings'];

            get(path, callback, args);
        }
    }

    this.geo = {
        search : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var path = '/svc/semantic/' + version + 'geocodes/query' + format + '?' + query + 'api-key=' + myKeys['geo'];
            get(path, callback, args);
        }
    }

    this.mostPopular = {
        emailed : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var section = args.section;
            var timePeriod = args['time-period'];
            var path = '/svc/mostpopular/' + version + 'mostemailed/' + section +
                '/' + timePeriod + format + '?' + query + 'api-key='+ myKeys['most-popular'];
            get(path, callback, args);
        },
        shared : function (args, callback) {
            if (!callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var section = args.section;
            var timePeriod = args['time-period'];
            var path = '/svc/mostpopular/' + version + 'mostshared/' + section +
                '/' + timePeriod + format + '?' + query + 'api-key=' + myKeys['most-popular'];
            get(path, callback, args);
        },
        viewed : function (args, callback) {
            if (! callback) {
                callback = args;
                args = undefined;
            }
            var version = 'v2/';
            var format = '.json';
            var query = '';
            if (querystring.stringify(args)) {
                query = querystring.stringify(args) + '&';
            }
            var section = args.section;
            var timePeriod = args['time-period'];
            var path = '/svc/mostpopular/' + version + 'mostviewed/' + section +
                '/' + timePeriod + format + '?' + query + 'api-key=' + myKeys['most-popular'];
            get(path, callback, args);
        }
    }
}

module.exports = nyt;
<|endoftext|>


<commit_before>var config;
if (typeof(require) === 'undefined') {
    require = { config: function (c) { config = c; } };
}
require.config({
    baseUrl: 'src',
    paths: {
        // Externals
        "almond":                                 "bower_components/almond/almond",
        "dropzone":                               "bower_components/dropzone/downloads/dropzone",
        "fine-uploader":                          "bower_components/fine-uploader/build/jquery.fineuploader",
        "jcrop":                                  "bower_components/jcrop/js/jquery.Jcrop",
        "jquery":                                 "bower_components/jquery/dist/jquery",
        "jquery.browser":                         "bower_components/jquery.browser/dist/jquery.browser",
        "jquery-hotkeys":                         "bower_components/raptor-dependencies/jquery-hotkeys",
        "jquery.anythingslider":                  "bower_components/AnythingSlider/js/jquery.anythingslider",
        "jquery.chosen":                          "bower_components/chosen/chosen/chosen.jquery",
        "jquery.form":                            "bower_components/jquery-form/jquery.form",
        "jquery.fullcalendar":                    "bower_components/fullcalendar/fullcalendar",
        "jquery.fullcalendar.dnd":                "bower_components/raptor-dependencies/jquery-ui",
        "jquery.placeholder":                     "bower_components/jquery-placeholder/jquery.placeholder.min",
        "jquery.textchange":                      "bower_components/jquery-textchange/jquery.textchange",
        "jquery.validation":                      "bower_components/jquery.validation/jquery.validate",
        "jquery.validation-additional-methods":   "bower_components/jquery.validation/additional-methods",
        "jqueryui":                               "bower_components/raptor-dependencies/jquery-ui",
        "less":                                   "bower_components/less.js/dist/less-1.6.2",
        "logging":                                "bower_components/logging/src/logging",
        "modernizr":                              "bower_components/modernizr/modernizr",
        "modernizr-csspositionsticky":            "bower_components/modernizr/feature-detects/css-positionsticky",
        "picker":                                 "bower_components/pickadate/lib/picker",
        "picker.date":                            "bower_components/pickadate/lib/picker.date",
        "picker.time":                            "bower_components/pickadate/lib/picker.time",
        "parsley":                                "bower_components/parsleyjs/parsley",
        "parsley.extend":                         "bower_components/parsleyjs/parsley.extend",
        "photoswipe":                             "bower_components/photoswipe/dist/photoswipe",
        "photoswipe-ui":                          "bower_components/photoswipe/dist/photoswipe-ui-default",
        "photoswipe-template":                    "bower_components/patternslib/src/pat/gallery/template",
        "pikaday":                                "bower_components/pikaday/pikaday",
        "prefixfree":                             "bower_components/prefixfree/prefixfree.min",
        "rangy-applier":                          "bower_components/raptor-dependencies/rangy/rangy-applier",
        "rangy-core":                             "bower_components/pat-raptor/lib/rangy-core",
        "rangy-cssclassapplier":                  "bower_components/raptor-dependencies/rangy/rangy-cssclassapplier",
        "rangy-selectionsaverestore":             "bower_components/raptor-dependencies/rangy/rangy-selectionsaverestore",
        "rangy-serializer":                       "bower_components/raptor-dependencies/rangy/rangy-serializer",
        "rangy-textrange":                        "bower_components/raptor-dependencies/rangy/rangy-textrange",
        "raptor":                                 "bower_components/pat-raptor/lib/raptor",
        "pat-raptor-image":                    "bower_components/pat-raptor/src/pat-raptor-image",
        "select2":                                "bower_components/select2/select2.min",
        "showdown":                               "bower_components/showdown/src/showdown",
        "showdown-github":                        "bower_components/showdown/src/extensions/github",
        "showdown-prettify":                      "bower_components/showdown/src/extensions/prettify",
        "showdown-table":                         "bower_components/showdown/src/extensions/table",
        "spectrum":                               "bower_components/spectrum/spectrum",
        "tpl":                                    "bower_components/requirejs-tpl-jcbrand/tpl",
        "text":                                   "bower_components/requirejs-text/text",
        "underscore":                             "bower_components/underscore/underscore",

        // Core
        "i18n":                      "bower_components/patternslib/src/core/i18n",
        "pat-base":                  "bower_components/patternslib/src/core/base",
        "pat-compat":                "bower_components/patternslib/src/core/compat",
        "pat-depends_parse":         "bower_components/patternslib/src/lib/depends_parse",
        "pat-dependshandler":        "bower_components/patternslib/src/lib/dependshandler",
        "pat-htmlparser":            "bower_components/patternslib/src/lib/htmlparser",
        "pat-input-change-events":   "bower_components/patternslib/src/lib/input-change-events",
        "pat-jquery-ext":            "bower_components/patternslib/src/core/jquery-ext",
        "pat-logger":                "bower_components/patternslib/src/core/logger",
        "pat-parser":                "bower_components/patternslib/src/core/parser",
        "pat-registry":              "bower_components/patternslib/src/core/registry",
        "pat-remove":                "bower_components/patternslib/src/core/remove",
        "pat-store":                 "bower_components/patternslib/src/core/store",
        "pat-url":                   "bower_components/patternslib/src/core/url",
        "pat-utils":                 "bower_components/patternslib/src/core/utils",

        // Patterns
        "pat-ajax":                  "bower_components/patternslib/src/pat/ajax/ajax",
        "pat-autofocus":             "bower_components/patternslib/src/pat/autofocus/autofocus",
        "pat-autoscale":             "bower_components/patternslib/src/pat/auto-scale/auto-scale",
        "pat-autosubmit":            "bower_components/patternslib/src/pat/auto-submit/auto-submit",
        "pat-autosuggest":           "bower_components/patternslib/src/pat/auto-suggest/auto-suggest",
        "pat-breadcrumbs":           "bower_components/patternslib/src/pat/breadcrumbs/breadcrumbs",
        "pat-bumper":                "bower_components/patternslib/src/pat/bumper/bumper",
        "pat-carousel":              "bower_components/patternslib/src/pat/carousel/carousel",
        "pat-checkedflag":           "bower_components/patternslib/src/pat/checked-flag/checked-flag",
        "pat-checklist":             "bower_components/patternslib/src/pat/checklist/checklist",
        "pat-chosen":                "bower_components/patternslib/src/pat/chosen/chosen",
        "pat-clone":                 "bower_components/patternslib/src/pat/clone/clone",
        "pat-collapsible":           "bower_components/patternslib/src/pat/collapsible/collapsible",
        "pat-content-mirror":        "bower_components/pat-content-mirror/src/pat-content-mirror",
        "pat-colour-picket":         "bower_components/patternslib/src/pat/colour-picker/colour-picker",
        "pat-date-picker":           "bower_components/patternslib/src/pat/date-picker/date-picker",
        "pat-display-time":          "bower_components/pat-display-time/src/pat-display-time",
        "pat-depends":               "bower_components/patternslib/src/pat/depends/depends",
        "pat-equaliser":             "bower_components/patternslib/src/pat/equaliser/equaliser",
        "pat-expandable":            "bower_components/patternslib/src/pat/expandable-tree/expandable-tree",
        "pat-focus":                 "bower_components/patternslib/src/pat/focus/focus",
        "pat-form-state":            "bower_components/patternslib/src/pat/form-state/form-state",
        "pat-forward":               "bower_components/patternslib/src/pat/forward/forward",
        "pat-calendar":              "bower_components/patternslib/src/pat/calendar/calendar",
        "pat-gallery":               "bower_components/patternslib/src/pat/gallery/gallery",
        "pat-image-crop":            "bower_components/patternslib/src/pat/image-crop/image-crop",
        "pat-inject":                "bower_components/patternslib/src/pat/inject/inject",
        "pat-legend":                "bower_components/patternslib/src/pat/legend/legend",
        "pat-markdown":              "bower_components/patternslib/src/pat/markdown/markdown",
        "pat-masonry":               "bower_components/patternslib/src/pat/masonry/masonry",
        "pat-menu":                  "bower_components/patternslib/src/pat/menu/menu",
        "pat-modal":                 "bower_components/patternslib/src/pat/modal/modal",
        "pat-navigation":            "bower_components/patternslib/src/pat/navigation/navigation",
        "pat-notification":          "bower_components/patternslib/src/pat/notification/notification",
        "pat-placeholder":           "bower_components/patternslib/src/pat/placeholder/placeholder",
        "pat-raptor":                "bower_components/pat-raptor/src/pat-raptor",
        "pat-resourcepolling":       "bower_components/pat-resourcepolling/src/pat-resourcepolling",
        "pat-selectbox":             "bower_components/patternslib/src/pat/selectbox/selectbox",
        "pat-slides":                "bower_components/patternslib/src/pat/slides/slides",
        "pat-slideshow-builder":     "bower_components/patternslib/src/pat/slideshow-builder/slideshow-builder",
        "pat-sortable":              "bower_components/patternslib/src/pat/sortable/sortable",
        "pat-stacks":                "bower_components/patternslib/src/pat/stacks/stacks",
        "pat-subform":               "bower_components/patternslib/src/pat/subform/subform",
        "pat-switch":                "bower_components/patternslib/src/pat/switch/switch",
        "pat-toggle":                "bower_components/patternslib/src/pat/toggle/toggle",
        "pat-tooltip":               "bower_components/patternslib/src/pat/tooltip/tooltip",
        "pat-upload":                "bower_components/pat-upload/src/pat-upload",
        "pat-validate":              "bower_components/patternslib/src/pat/validate/validate",
        "pat-zoom":                  "bower_components/patternslib/src/pat/zoom/zoom",
        "patterns":                  "patterns",

        // Templates for pat-upload
        "preview":  "bower_components/pat-upload/src/templates/preview.xml",
        "upload":   "bower_components/pat-upload/src/templates/upload.xml",

        //Calendar Pattern
        "moment":           "bower_components/moment/moment",
        "moment-timezone":  "bower_components/moment-timezone/moment-timezone",
        "pat-calendar-moment-timezone-data": "bower_components/pat-calendar/src/moment-timezone-data",

        // Pat Masonry
        "doc-ready":            "bower_components/doc-ready",
        "eventEmitter":         "bower_components/eventEmitter",
        "eventie":              "bower_components/eventie",
        "get-size":             "bower_components/get-size",
        "get-style-property":   "bower_components/get-style-property",
        "imagesloaded":         "bower_components/imagesloaded/imagesloaded",
        "masonry":              "bower_components/masonry/masonry",
        "matches-selector":     "bower_components/matches-selector",
        "outlayer":             "bower_components/outlayer",

        "mockup-parser":            "bower_components/mockup-core/js/parser",
        "mockup-patterns-base":     "bower_components/mockup-core/js/pattern"
    },

    shim: {
        "fine-uploader":                { deps: ["jquery"] },
        "jcrop":                        { deps: ["jquery"] },
        "jquery":                       { exports: "jQuery" },
        "jquery-hotkeys":               { deps: ["jquery"] },
        "jquery.anythingslider":        { deps: ["jquery"] },
        "jquery.chosen":                { deps: ["jquery"] },
        "jquery.fullcalendar.dnd":      { deps: ["jquery"] },
        "jquery.placeholder":           { deps: ["jquery"] },
        "jquery.textchange":            { deps: ["jquery"] },
        "jqueryui":                     { deps: ["jquery"] },
        "modernizr-csspositionsticky":  { deps: ["modernizr"] },
        "parsley":                      { deps: ["jquery"] },
        "parsley.extend":               { deps: ["jquery"] },
        "select2":                      { deps: ["jquery"] },
        "showdown-github":              { deps: ["showdown"] },
        "showdown-prettify":            { deps: ["showdown", "google-code-prettify"] },
        "showdown-table":               { deps: ["showdown"] },
        "spectrum":                     { deps: ["jquery"] },
        "tinymce":                      { deps: ["jquery"] },
        "rangy-applier":                { deps: ["rangy-core"] },
        "rangy-core":                   { exports: "rangy" },
        "rangy-cssclassapplier":        { deps: ["rangy-core"] },
        "rangy-selectionsaverestore":   { deps: ["rangy-core"] },
        "rangy-serializer":             { deps: ["rangy-core"] },
        "rangy-textrange":              { deps: ["rangy-core"] },
        "raptor":                       { exports: "$.fn.raptor.Raptor",
                                          deps: [
                                            "jquery",
                                            "jqueryui",
                                            "jquery-hotkeys",
                                            "rangy-applier",
                                            "rangy-cssclassapplier",
                                            "rangy-selectionsaverestore",
                                            "rangy-serializer",
                                            "rangy-textrange",
                                          ]}
    }
});

if (typeof(require) === 'function') {
    require(["patterns"], function(patterns) {});
}
<commit_msg>adding requirejs mapping for pat-raptor-link-tooltip<commit_after>var config;
if (typeof(require) === 'undefined') {
    require = { config: function (c) { config = c; } };
}
require.config({
    baseUrl: 'src',
    paths: {
        // Externals
        "almond":                                 "bower_components/almond/almond",
        "dropzone":                               "bower_components/dropzone/downloads/dropzone",
        "fine-uploader":                          "bower_components/fine-uploader/build/jquery.fineuploader",
        "jcrop":                                  "bower_components/jcrop/js/jquery.Jcrop",
        "jquery":                                 "bower_components/jquery/dist/jquery",
        "jquery.browser":                         "bower_components/jquery.browser/dist/jquery.browser",
        "jquery-hotkeys":                         "bower_components/raptor-dependencies/jquery-hotkeys",
        "jquery.anythingslider":                  "bower_components/AnythingSlider/js/jquery.anythingslider",
        "jquery.chosen":                          "bower_components/chosen/chosen/chosen.jquery",
        "jquery.form":                            "bower_components/jquery-form/jquery.form",
        "jquery.fullcalendar":                    "bower_components/fullcalendar/fullcalendar",
        "jquery.fullcalendar.dnd":                "bower_components/raptor-dependencies/jquery-ui",
        "jquery.placeholder":                     "bower_components/jquery-placeholder/jquery.placeholder.min",
        "jquery.textchange":                      "bower_components/jquery-textchange/jquery.textchange",
        "jquery.validation":                      "bower_components/jquery.validation/jquery.validate",
        "jquery.validation-additional-methods":   "bower_components/jquery.validation/additional-methods",
        "jqueryui":                               "bower_components/raptor-dependencies/jquery-ui",
        "less":                                   "bower_components/less.js/dist/less-1.6.2",
        "logging":                                "bower_components/logging/src/logging",
        "modernizr":                              "bower_components/modernizr/modernizr",
        "modernizr-csspositionsticky":            "bower_components/modernizr/feature-detects/css-positionsticky",
        "picker":                                 "bower_components/pickadate/lib/picker",
        "picker.date":                            "bower_components/pickadate/lib/picker.date",
        "picker.time":                            "bower_components/pickadate/lib/picker.time",
        "parsley":                                "bower_components/parsleyjs/parsley",
        "parsley.extend":                         "bower_components/parsleyjs/parsley.extend",
        "photoswipe":                             "bower_components/photoswipe/dist/photoswipe",
        "photoswipe-ui":                          "bower_components/photoswipe/dist/photoswipe-ui-default",
        "photoswipe-template":                    "bower_components/patternslib/src/pat/gallery/template",
        "pikaday":                                "bower_components/pikaday/pikaday",
        "prefixfree":                             "bower_components/prefixfree/prefixfree.min",
        "rangy-applier":                          "bower_components/raptor-dependencies/rangy/rangy-applier",
        "rangy-core":                             "bower_components/pat-raptor/lib/rangy-core",
        "rangy-cssclassapplier":                  "bower_components/raptor-dependencies/rangy/rangy-cssclassapplier",
        "rangy-selectionsaverestore":             "bower_components/raptor-dependencies/rangy/rangy-selectionsaverestore",
        "rangy-serializer":                       "bower_components/raptor-dependencies/rangy/rangy-serializer",
        "rangy-textrange":                        "bower_components/raptor-dependencies/rangy/rangy-textrange",
        "raptor":                                 "bower_components/pat-raptor/lib/raptor",
        "pat-raptor-image":                       "bower_components/pat-raptor/src/pat-raptor-image",
        "pat-raptor-link-tooltip":                "bower_components/pat-raptor/src/pat-raptor-link-tooltip",
        "select2":                                "bower_components/select2/select2.min",
        "showdown":                               "bower_components/showdown/src/showdown",
        "showdown-github":                        "bower_components/showdown/src/extensions/github",
        "showdown-prettify":                      "bower_components/showdown/src/extensions/prettify",
        "showdown-table":                         "bower_components/showdown/src/extensions/table",
        "spectrum":                               "bower_components/spectrum/spectrum",
        "tpl":                                    "bower_components/requirejs-tpl-jcbrand/tpl",
        "text":                                   "bower_components/requirejs-text/text",
        "underscore":                             "bower_components/underscore/underscore",

        // Core
        "i18n":                      "bower_components/patternslib/src/core/i18n",
        "pat-base":                  "bower_components/patternslib/src/core/base",
        "pat-compat":                "bower_components/patternslib/src/core/compat",
        "pat-depends_parse":         "bower_components/patternslib/src/lib/depends_parse",
        "pat-dependshandler":        "bower_components/patternslib/src/lib/dependshandler",
        "pat-htmlparser":            "bower_components/patternslib/src/lib/htmlparser",
        "pat-input-change-events":   "bower_components/patternslib/src/lib/input-change-events",
        "pat-jquery-ext":            "bower_components/patternslib/src/core/jquery-ext",
        "pat-logger":                "bower_components/patternslib/src/core/logger",
        "pat-parser":                "bower_components/patternslib/src/core/parser",
        "pat-registry":              "bower_components/patternslib/src/core/registry",
        "pat-remove":                "bower_components/patternslib/src/core/remove",
        "pat-store":                 "bower_components/patternslib/src/core/store",
        "pat-url":                   "bower_components/patternslib/src/core/url",
        "pat-utils":                 "bower_components/patternslib/src/core/utils",

        // Patterns
        "pat-ajax":                  "bower_components/patternslib/src/pat/ajax/ajax",
        "pat-autofocus":             "bower_components/patternslib/src/pat/autofocus/autofocus",
        "pat-autoscale":             "bower_components/patternslib/src/pat/auto-scale/auto-scale",
        "pat-autosubmit":            "bower_components/patternslib/src/pat/auto-submit/auto-submit",
        "pat-autosuggest":           "bower_components/patternslib/src/pat/auto-suggest/auto-suggest",
        "pat-breadcrumbs":           "bower_components/patternslib/src/pat/breadcrumbs/breadcrumbs",
        "pat-bumper":                "bower_components/patternslib/src/pat/bumper/bumper",
        "pat-carousel":              "bower_components/patternslib/src/pat/carousel/carousel",
        "pat-checkedflag":           "bower_components/patternslib/src/pat/checked-flag/checked-flag",
        "pat-checklist":             "bower_components/patternslib/src/pat/checklist/checklist",
        "pat-chosen":                "bower_components/patternslib/src/pat/chosen/chosen",
        "pat-clone":                 "bower_components/patternslib/src/pat/clone/clone",
        "pat-collapsible":           "bower_components/patternslib/src/pat/collapsible/collapsible",
        "pat-content-mirror":        "bower_components/pat-content-mirror/src/pat-content-mirror",
        "pat-colour-picket":         "bower_components/patternslib/src/pat/colour-picker/colour-picker",
        "pat-date-picker":           "bower_components/patternslib/src/pat/date-picker/date-picker",
        "pat-display-time":          "bower_components/pat-display-time/src/pat-display-time",
        "pat-depends":               "bower_components/patternslib/src/pat/depends/depends",
        "pat-equaliser":             "bower_components/patternslib/src/pat/equaliser/equaliser",
        "pat-expandable":            "bower_components/patternslib/src/pat/expandable-tree/expandable-tree",
        "pat-focus":                 "bower_components/patternslib/src/pat/focus/focus",
        "pat-form-state":            "bower_components/patternslib/src/pat/form-state/form-state",
        "pat-forward":               "bower_components/patternslib/src/pat/forward/forward",
        "pat-calendar":              "bower_components/patternslib/src/pat/calendar/calendar",
        "pat-gallery":               "bower_components/patternslib/src/pat/gallery/gallery",
        "pat-image-crop":            "bower_components/patternslib/src/pat/image-crop/image-crop",
        "pat-inject":                "bower_components/patternslib/src/pat/inject/inject",
        "pat-legend":                "bower_components/patternslib/src/pat/legend/legend",
        "pat-markdown":              "bower_components/patternslib/src/pat/markdown/markdown",
        "pat-masonry":               "bower_components/patternslib/src/pat/masonry/masonry",
        "pat-menu":                  "bower_components/patternslib/src/pat/menu/menu",
        "pat-modal":                 "bower_components/patternslib/src/pat/modal/modal",
        "pat-navigation":            "bower_components/patternslib/src/pat/navigation/navigation",
        "pat-notification":          "bower_components/patternslib/src/pat/notification/notification",
        "pat-placeholder":           "bower_components/patternslib/src/pat/placeholder/placeholder",
        "pat-raptor":                "bower_components/pat-raptor/src/pat-raptor",
        "pat-resourcepolling":       "bower_components/pat-resourcepolling/src/pat-resourcepolling",
        "pat-selectbox":             "bower_components/patternslib/src/pat/selectbox/selectbox",
        "pat-slides":                "bower_components/patternslib/src/pat/slides/slides",
        "pat-slideshow-builder":     "bower_components/patternslib/src/pat/slideshow-builder/slideshow-builder",
        "pat-sortable":              "bower_components/patternslib/src/pat/sortable/sortable",
        "pat-stacks":                "bower_components/patternslib/src/pat/stacks/stacks",
        "pat-subform":               "bower_components/patternslib/src/pat/subform/subform",
        "pat-switch":                "bower_components/patternslib/src/pat/switch/switch",
        "pat-toggle":                "bower_components/patternslib/src/pat/toggle/toggle",
        "pat-tooltip":               "bower_components/patternslib/src/pat/tooltip/tooltip",
        "pat-upload":                "bower_components/pat-upload/src/pat-upload",
        "pat-validate":              "bower_components/patternslib/src/pat/validate/validate",
        "pat-zoom":                  "bower_components/patternslib/src/pat/zoom/zoom",
        "patterns":                  "patterns",

        // Templates for pat-upload
        "preview":  "bower_components/pat-upload/src/templates/preview.xml",
        "upload":   "bower_components/pat-upload/src/templates/upload.xml",

        //Calendar Pattern
        "moment":           "bower_components/moment/moment",
        "moment-timezone":  "bower_components/moment-timezone/moment-timezone",
        "pat-calendar-moment-timezone-data": "bower_components/pat-calendar/src/moment-timezone-data",

        // Pat Masonry
        "doc-ready":            "bower_components/doc-ready",
        "eventEmitter":         "bower_components/eventEmitter",
        "eventie":              "bower_components/eventie",
        "get-size":             "bower_components/get-size",
        "get-style-property":   "bower_components/get-style-property",
        "imagesloaded":         "bower_components/imagesloaded/imagesloaded",
        "masonry":              "bower_components/masonry/masonry",
        "matches-selector":     "bower_components/matches-selector",
        "outlayer":             "bower_components/outlayer",

        "mockup-parser":            "bower_components/mockup-core/js/parser",
        "mockup-patterns-base":     "bower_components/mockup-core/js/pattern"
    },

    shim: {
        "fine-uploader":                { deps: ["jquery"] },
        "jcrop":                        { deps: ["jquery"] },
        "jquery":                       { exports: "jQuery" },
        "jquery-hotkeys":               { deps: ["jquery"] },
        "jquery.anythingslider":        { deps: ["jquery"] },
        "jquery.chosen":                { deps: ["jquery"] },
        "jquery.fullcalendar.dnd":      { deps: ["jquery"] },
        "jquery.placeholder":           { deps: ["jquery"] },
        "jquery.textchange":            { deps: ["jquery"] },
        "jqueryui":                     { deps: ["jquery"] },
        "modernizr-csspositionsticky":  { deps: ["modernizr"] },
        "parsley":                      { deps: ["jquery"] },
        "parsley.extend":               { deps: ["jquery"] },
        "select2":                      { deps: ["jquery"] },
        "showdown-github":              { deps: ["showdown"] },
        "showdown-prettify":            { deps: ["showdown", "google-code-prettify"] },
        "showdown-table":               { deps: ["showdown"] },
        "spectrum":                     { deps: ["jquery"] },
        "tinymce":                      { deps: ["jquery"] },
        "rangy-applier":                { deps: ["rangy-core"] },
        "rangy-core":                   { exports: "rangy" },
        "rangy-cssclassapplier":        { deps: ["rangy-core"] },
        "rangy-selectionsaverestore":   { deps: ["rangy-core"] },
        "rangy-serializer":             { deps: ["rangy-core"] },
        "rangy-textrange":              { deps: ["rangy-core"] },
        "raptor":                       { exports: "$.fn.raptor.Raptor",
                                          deps: [
                                            "jquery",
                                            "jqueryui",
                                            "jquery-hotkeys",
                                            "rangy-applier",
                                            "rangy-cssclassapplier",
                                            "rangy-selectionsaverestore",
                                            "rangy-serializer",
                                            "rangy-textrange",
                                          ]}
    }
});

if (typeof(require) === 'function') {
    require(["patterns"], function(patterns) {});
}
<|endoftext|>


<commit_before>const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const {BrowserWindow, Tray} = require('electron')

const path = require('path')
const url = require('url')
const Menu = electron.Menu
const ipc = electron.ipcMain
const dialog = electron.dialog
const shell = electron.shell
const globalShortcut = electron.globalShortcut
let quote = require('./build/assets/js/quote.js');

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow

function createWindow () {
  // Create the browser window.

  let windowOptions = {
    width: 650,
    height: 12 * 2 + 12 + 8 + (32 + 2) * 18,
    maximizable: false,
    resizable: false,
    autoHideMenuBar: true,
    frame: false
  }

  if(process.platform === 'linux') {
    windowOptions.icon = path.join(__dirname, '/build/assets/img/logo.png');
  }

  mainWindow = new BrowserWindow(windowOptions);

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
app.on('ready', () => {
  globalShortcut.register('CommandOrControl+Alt+Q', function () {
    mainWindow.close();
  })
})

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow()
  }
})

app.on('will-quit', () => {
  globalShortcut.unregisterAll();
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

let appIcon = null
let iconName

ipc.on('put-in-tray',  (event) => {

  if(process.platform === 'win32') {
    iconName = '/build/assets/img/logo.ico';

  } else if(process.platform === 'darwin') {
    iconName = '/build/assets/img/logo.icns';

  } else {
    iconName = '/build/assets/img/logo.png';
  }

  const iconPath = path.join(__dirname, iconName)
  appIcon = new Tray(iconPath)
  const contextMenu = Menu.buildFromTemplate([

  {
    label: 'About',
    click: () => {
      shell.openExternal('https://theiyd.github.io/source-me/index.html');
    },
  },

  {
    label: 'Quote of the Day',
    click: () => {
      quote.quoteWindow();
    }
  },

  {
    label: 'Other Resources',
    submenu: [
      {
        label: 'JSPlaygrounds',
        click: () => {
          shell.openExternal('https://stephengrider.github.io/JSPlaygrounds/');
        }
      },

      {
        label: 'W3Schools',
        click: () => {
          shell.openExternal('https://www.w3schools.com/');
        }
      },

      {
        label: 'CSS Tricks',
        click: () => {
          shell.openExternal('https://css-tricks.com/');
        }
      }
    ]
  },

  {
    label: 'Quit',
    click: () => {
      //event.sender.send('tray-removed')
      app.quit();
    }
  }])

  appIcon.setToolTip('Source Me in tray.')
  appIcon.setContextMenu(contextMenu)
})

ipc.on('remove-tray', () => {
  appIcon.destroy()
})

app.on('window-all-closed', () => {
  if (appIcon) {
    appIcon.destroy()
  }
})<commit_msg>fixed icon<commit_after>const electron = require('electron')
// Module to control application life.
const app = electron.app
// Module to create native browser window.
const {BrowserWindow, Tray} = require('electron')

const path = require('path')
const url = require('url')
const Menu = electron.Menu
const ipc = electron.ipcMain
const dialog = electron.dialog
const shell = electron.shell
const globalShortcut = electron.globalShortcut
let quote = require('./build/assets/js/quote.js')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow

function createWindow () {
  // Create the browser window.

  let windowOptions = {
    width: 650,
    height: 12 * 2 + 12 + 8 + (32 + 2) * 18,
    maximizable: false,
    resizable: false,
    autoHideMenuBar: true,
    frame: false
  }

  if (process.platform === 'linux') {
    windowOptions.icon = path.join(__dirname, '/build/assets/img/logo.png')
  }

  mainWindow = new BrowserWindow(windowOptions)

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }))

  // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)
app.on('ready', () => {
  globalShortcut.register('CommandOrControl+Alt+Q', function () {
    mainWindow.close()
  })
})

// Quit when all windows are closed.
app.on('window-all-closed', function () {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', function () {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow()
  }
})

app.on('will-quit', () => {
  globalShortcut.unregisterAll()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

let appIcon = null
let iconName

ipc.on('put-in-tray', (event) => {
  if (process.platform === 'win32') {
    iconName = '/build/assets/img/logo.ico'
  } else {
    iconName = '/build/assets/img/logo.png'
  }

  const iconPath = path.join(__dirname, iconName)
  appIcon = new Tray(iconPath)
  const contextMenu = Menu.buildFromTemplate([

    {
      label: 'About',
      click: () => {
        shell.openExternal('https://theiyd.github.io/source-me/index.html')
      }
    },

    {
      label: 'Quote of the Day',
      click: () => {
        quote.quoteWindow()
      }
    },

    {
      label: 'Other Resources',
      submenu: [
        {
          label: 'JSPlaygrounds',
          click: () => {
            shell.openExternal('https://stephengrider.github.io/JSPlaygrounds/')
          }
        },

        {
          label: 'W3Schools',
          click: () => {
            shell.openExternal('https://www.w3schools.com/')
          }
        },

        {
          label: 'CSS Tricks',
          click: () => {
            shell.openExternal('https://css-tricks.com/')
          }
        }
      ]
    },

    {
      label: 'Quit',
      click: () => {
      // event.sender.send('tray-removed')
        app.quit()
      }
    }])

  appIcon.setToolTip('Source Me in tray.')
  appIcon.setContextMenu(contextMenu)
})

ipc.on('remove-tray', () => {
  appIcon.destroy()
})

app.on('window-all-closed', () => {
  if (appIcon) {
    appIcon.destroy()
  }
})
<|endoftext|>


<commit_before>const {
  app,
  shell,
  Menu,
  BrowserWindow,
  globalShortcut,
  session,
} = require('electron') // eslint-disable-line import/no-extraneous-dependencies
const path = require('path')
const url = require('url')
const { autoUpdater } = require('electron-updater')
const log = require('electron-log')

const port = process.env.PORT || 3000

let mainWindow = null

// adapted from https://github.com/chentsulin/electron-react-boilerplate
const installExtensions = () => {
  const installer = require('electron-devtools-installer') // eslint-disable-line import/no-extraneous-dependencies
  const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS']

  return Promise.all(
    extensions.map(name => installer.default(installer[name])),
  ).catch(console.error)
}

app.on('window-all-closed', () => {
  app.quit()
})

app.on('ready', () => {
  // https://github.com/electron/electron/blob/master/docs/tutorial/security.md#csp-http-header
  session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
    callback({ responseHeaders: "default-src 'none'" }) // eslint-disable-line
  })
  const onAppReady = () => {
    mainWindow = new BrowserWindow({
      height: 750,
      width: 1200,
      minHeight: 750,
      minWidth: 1200,
      titleBarStyle: 'hidden',
      frame: false,
      show: false,
      icon: path.join(__dirname, 'icons/png/64x64.png'),
      contextIsolation: true,
      webPreferences: {
        allowRunningInsecureContent: false,
        webSecurity: true,
        nodeIntegration: false,
        preload: path.join(__dirname, 'preload.js'),
      },
    })

    autoUpdater.checkForUpdatesAndNotify()

    mainWindow.on('ready-to-show', () => {
      mainWindow.show()
      mainWindow.focus()
    })

    // https://discuss.atom.io/t/prevent-window-navigation-when-dropping-a-link/24365
    mainWindow.webContents.on('will-navigate', ev => {
      ev.preventDefault()
    })

    if (process.env.NODE_ENV === 'development') {
      mainWindow.webContents.once('dom-ready', () => {
        mainWindow.webContents.openDevTools()
      })
    }

    if (process.platform !== 'darwin') {
      // Windows/Linux Menu
      mainWindow.setMenu(null)
    } else {
      // Menu is required for MacOS
      const template = [
        {
          label: app.getName(),
          submenu: [{ role: 'about' }, { type: 'separator' }, { role: 'quit' }],
        },
        {
          label: 'Edit',
          submenu: [
            { role: 'undo' },
            { role: 'redo' },
            { type: 'separator' },
            { role: 'cut' },
            { role: 'copy' },
            { role: 'paste' },
          ],
        },
        {
          label: 'View',
          submenu: [{ role: 'toggledevtools' }],
        },
        {
          role: 'help',
          submenu: [
            {
              label: 'City of Zion',
              click() {
                shell.openExternal('https://cityofzion.io/')
              },
            },
            {
              label: 'GitHub',
              click() {
                shell.openExternal('https://github.com/CityOfZion')
              },
            },
            {
              label: 'NEO Reddit',
              click() {
                shell.openExternal('https://www.reddit.com/r/NEO/')
              },
            },
            {
              label: 'Slack',
              click() {
                shell.openExternal('https://neosmarteconomy.slack.com')
              },
            },
          ],
        },
      ]
      const menu = Menu.buildFromTemplate(template)
      Menu.setApplicationMenu(menu)
    }

    const inputMenu = Menu.buildFromTemplate([
      {
        label: 'Paste',
        accelerator: 'CmdOrCtrl+V',
        click() {
          mainWindow.webContents.paste()
        },
      },
    ])

    mainWindow.webContents.on('context-menu', () => {
      inputMenu.popup(mainWindow)
    })

    if (process.env.START_HOT) {
      mainWindow.loadURL(`http://localhost:${port}/dist`)
    } else {
      mainWindow.loadURL(
        url.format({
          protocol: 'file',
          slashes: true,
          pathname: path.join(__dirname, '/app/dist/index.html'),
        }),
      )
    }
    mainWindow.on('closed', () => {
      mainWindow = null
    })
  }

  // register any shortcuts here
  globalShortcut.register('CommandOrControl+M', () => {
    mainWindow.minimize()
  })

  if (process.env.NODE_ENV === 'development') {
    installExtensions().then(() => onAppReady())
  } else {
    onAppReady()
  }
})

app.on('web-contents-created', (event, wc) => {
  wc.on('before-input-event', (event, input) => {
    // Windows/Linux hotkeys
    if (process.platform !== 'darwin') {
      if (input.key === 'F12') {
        mainWindow.webContents.openDevTools()
        event.preventDefault()
      }
    }
  })
})

app.on('will-quit', () => {
  // Unregister all shortcuts.
  globalShortcut.unregisterAll()
})

autoUpdater.logger = log
autoUpdater.logger.transports.file.level = 'info'

function sendStatusToWindow(text) {
  log.info(text)
  mainWindow.webContents.send('message', text)
}

autoUpdater.on('checking-for-update', () => {
  sendStatusToWindow('Checking for update...')
})
autoUpdater.on('update-available', info => {
  // eslint-disable-next-line prefer-template
  sendStatusToWindow('Update available. ' + info)
})
autoUpdater.on('update-not-available', () => {
  sendStatusToWindow('Update not available.')
})
autoUpdater.on('error', err => {
  // eslint-disable-next-line prefer-template
  sendStatusToWindow('Error in auto-updater. ' + err)
})
autoUpdater.on('download-progress', progressObj => {
  // eslint-disable-next-line prefer-template
  let logMessage = 'Download speed: ' + progressObj.bytesPerSecond
  // eslint-disable-next-line prefer-template
  logMessage = logMessage + ' - Downloaded ' + progressObj.percent + '%'
  logMessage =
    // eslint-disable-next-line prefer-template
    logMessage + ' (' + progressObj.transferred + '/' + progressObj.total + ')'
  sendStatusToWindow(logMessage)
})
autoUpdater.on('update-downloaded', info => {
  // eslint-disable-next-line prefer-template
  sendStatusToWindow('Update downloaded ' + info)
})
<commit_msg>Revert frameless mode<commit_after>const {
  app,
  shell,
  Menu,
  BrowserWindow,
  globalShortcut,
  session,
} = require('electron') // eslint-disable-line import/no-extraneous-dependencies
const path = require('path')
const url = require('url')
const { autoUpdater } = require('electron-updater')
const log = require('electron-log')

const port = process.env.PORT || 3000

let mainWindow = null

// adapted from https://github.com/chentsulin/electron-react-boilerplate
const installExtensions = () => {
  const installer = require('electron-devtools-installer') // eslint-disable-line import/no-extraneous-dependencies
  const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS']

  return Promise.all(
    extensions.map(name => installer.default(installer[name])),
  ).catch(console.error)
}

app.on('window-all-closed', () => {
  app.quit()
})

app.on('ready', () => {
  // https://github.com/electron/electron/blob/master/docs/tutorial/security.md#csp-http-header
  session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
    callback({ responseHeaders: "default-src 'none'" }) // eslint-disable-line
  })
  const onAppReady = () => {
    mainWindow = new BrowserWindow({
      height: 750,
      width: 1200,
      minHeight: 750,
      minWidth: 1200,
      titleBarStyle: 'hidden',
      show: false,
      icon: path.join(__dirname, 'icons/png/64x64.png'),
      contextIsolation: true,
      webPreferences: {
        allowRunningInsecureContent: false,
        webSecurity: true,
        nodeIntegration: false,
        preload: path.join(__dirname, 'preload.js'),
      },
    })

    autoUpdater.checkForUpdatesAndNotify()

    mainWindow.on('ready-to-show', () => {
      mainWindow.show()
      mainWindow.focus()
    })

    // https://discuss.atom.io/t/prevent-window-navigation-when-dropping-a-link/24365
    mainWindow.webContents.on('will-navigate', ev => {
      ev.preventDefault()
    })

    if (process.env.NODE_ENV === 'development') {
      mainWindow.webContents.once('dom-ready', () => {
        mainWindow.webContents.openDevTools()
      })
    }

    if (process.platform !== 'darwin') {
      // Windows/Linux Menu
      mainWindow.setMenu(null)
    } else {
      // Menu is required for MacOS
      const template = [
        {
          label: app.getName(),
          submenu: [{ role: 'about' }, { type: 'separator' }, { role: 'quit' }],
        },
        {
          label: 'Edit',
          submenu: [
            { role: 'undo' },
            { role: 'redo' },
            { type: 'separator' },
            { role: 'cut' },
            { role: 'copy' },
            { role: 'paste' },
          ],
        },
        {
          label: 'View',
          submenu: [{ role: 'toggledevtools' }],
        },
        {
          role: 'help',
          submenu: [
            {
              label: 'City of Zion',
              click() {
                shell.openExternal('https://cityofzion.io/')
              },
            },
            {
              label: 'GitHub',
              click() {
                shell.openExternal('https://github.com/CityOfZion')
              },
            },
            {
              label: 'NEO Reddit',
              click() {
                shell.openExternal('https://www.reddit.com/r/NEO/')
              },
            },
            {
              label: 'Slack',
              click() {
                shell.openExternal('https://neosmarteconomy.slack.com')
              },
            },
          ],
        },
      ]
      const menu = Menu.buildFromTemplate(template)
      Menu.setApplicationMenu(menu)
    }

    const inputMenu = Menu.buildFromTemplate([
      {
        label: 'Paste',
        accelerator: 'CmdOrCtrl+V',
        click() {
          mainWindow.webContents.paste()
        },
      },
    ])

    mainWindow.webContents.on('context-menu', () => {
      inputMenu.popup(mainWindow)
    })

    if (process.env.START_HOT) {
      mainWindow.loadURL(`http://localhost:${port}/dist`)
    } else {
      mainWindow.loadURL(
        url.format({
          protocol: 'file',
          slashes: true,
          pathname: path.join(__dirname, '/app/dist/index.html'),
        }),
      )
    }
    mainWindow.on('closed', () => {
      mainWindow = null
    })
  }

  // register any shortcuts here
  globalShortcut.register('CommandOrControl+M', () => {
    mainWindow.minimize()
  })

  if (process.env.NODE_ENV === 'development') {
    installExtensions().then(() => onAppReady())
  } else {
    onAppReady()
  }
})

app.on('web-contents-created', (event, wc) => {
  wc.on('before-input-event', (event, input) => {
    // Windows/Linux hotkeys
    if (process.platform !== 'darwin') {
      if (input.key === 'F12') {
        mainWindow.webContents.openDevTools()
        event.preventDefault()
      }
    }
  })
})

app.on('will-quit', () => {
  // Unregister all shortcuts.
  globalShortcut.unregisterAll()
})

autoUpdater.logger = log
autoUpdater.logger.transports.file.level = 'info'

function sendStatusToWindow(text) {
  log.info(text)
  mainWindow.webContents.send('message', text)
}

autoUpdater.on('checking-for-update', () => {
  sendStatusToWindow('Checking for update...')
})
autoUpdater.on('update-available', info => {
  // eslint-disable-next-line prefer-template
  sendStatusToWindow('Update available. ' + info)
})
autoUpdater.on('update-not-available', () => {
  sendStatusToWindow('Update not available.')
})
autoUpdater.on('error', err => {
  // eslint-disable-next-line prefer-template
  sendStatusToWindow('Error in auto-updater. ' + err)
})
autoUpdater.on('download-progress', progressObj => {
  // eslint-disable-next-line prefer-template
  let logMessage = 'Download speed: ' + progressObj.bytesPerSecond
  // eslint-disable-next-line prefer-template
  logMessage = logMessage + ' - Downloaded ' + progressObj.percent + '%'
  logMessage =
    // eslint-disable-next-line prefer-template
    logMessage + ' (' + progressObj.transferred + '/' + progressObj.total + ')'
  sendStatusToWindow(logMessage)
})
autoUpdater.on('update-downloaded', info => {
  // eslint-disable-next-line prefer-template
  sendStatusToWindow('Update downloaded ' + info)
})
<|endoftext|>


<commit_before>var app = require("app");
var BrowserWindow = require("browser-window");
var env = require("node-env-file");

var mainWindow = null;
var environment = env(__dirname + "/.env")["ENV"];

app.on("window-all-closed", function() {
  if (process.platform != "darwin")
    app.quit();
});

var Tray = require("tray");
var Menu = require("menu");
var ipc = require("ipc");

app.on("ready", function() {
  app.commandLine.appendSwitch("disable-web-security");
  mainWindow = new BrowserWindow({
    width: 1000,
    height: 800,
    "web-preferences": {
      "web-security": false
    }
  });

  mainWindow.module = undefined;
  mainWindow.setTitle("NeverAgain");
  if(environment === "development"){
    mainWindow.setMenuBarVisibility(false);
    mainWindow.setAutoHideMenuBar(true);
    mainWindow.setSkipTaskbar(true);
    mainWindow.setSkipTaskbar(false);
    mainWindow.openDevTools();
    mainWindow.setSize(1200, 1200);
    mainWindow.loadUrl("http://localhost:4200/");
  } else if (environment === "production"){
    mainWindow.loadUrl("file://" + __dirname + "/index.html");
    // app.dock.hide();
    mainWindow.setResizable(false);
  } else {
    throw "not supported " + environment;
  }

  mainWindow.center();

  // var toggle = {
  //   "true":  "assets/star-o.png",
  //   "false": "assets/star.png"
  // }

  // appIcon = new Tray(toggle["true"]);
  // appIcon.on("clicked", function() {
  //   appIcon.setImage(toggle["false"])
  //   mainWindow.focus();
  // });

  ipc.on("newBackgroundEpisodes", function(event, arg) {
    if(!mainWindow.isFocused()){
      // appIcon.setImage(toggle["false"]);
    }
  });

  mainWindow.webContents.on("new-window", function(e, url) {
    require("shell").openExternal(url);
    e.preventDefault()
  });

  mainWindow.on("focus", function() {
    // appIcon.setImage(toggle["true"]);
  });
});<commit_msg>Fix tray problem<commit_after>var app = require("app");
var BrowserWindow = require("browser-window");
var env = require("node-env-file");

var mainWindow = null;
var environment = env(__dirname + "/.env")["ENV"];

app.on("window-all-closed", function() {
  if (process.platform != "darwin")
    app.quit();
});

var Tray = require("tray");
var Menu = require("menu");
var ipc = require("ipc");
var path = require("path");

app.on("ready", function() {
  app.commandLine.appendSwitch("disable-web-security");
  mainWindow = new BrowserWindow({
    width: 1000,
    height: 800,
    "web-preferences": {
      "web-security": false
    }
  });

  mainWindow.module = undefined;
  mainWindow.setTitle("NeverAgain");
  if(environment === "development"){
    mainWindow.setMenuBarVisibility(false);
    mainWindow.setAutoHideMenuBar(true);
    mainWindow.setSkipTaskbar(true);
    mainWindow.setSkipTaskbar(false);
    mainWindow.openDevTools();
    mainWindow.setSize(1200, 1200);
    mainWindow.loadUrl("http://localhost:4200/");
  } else if (environment === "production"){
    mainWindow.loadUrl("file://" + __dirname + "/index.html");
    // app.dock.hide();
    mainWindow.setResizable(false);
  } else {
    throw "not supported " + environment;
  }

  mainWindow.center();

  var currentPath = path.dirname(require.main.filename);
  var toggle = {
    "true":  currentPath + "/assets/star-o.png",
    "false": currentPath + "/assets/star.png"
  }

  appIcon = new Tray(toggle["true"]);

  appIcon.on("clicked", function() {
    appIcon.setImage(toggle["false"])
    mainWindow.focus();
  });

  ipc.on("newBackgroundEpisodes", function(event, arg) {
    if(!mainWindow.isFocused()){
      appIcon.setImage(toggle["false"]);
    }
  });

  mainWindow.webContents.on("new-window", function(e, url) {
    require("shell").openExternal(url);
    e.preventDefault()
  });

  mainWindow.on("focus", function() {
    appIcon.setImage(toggle["true"]);
  });
});<|endoftext|>