<commit_before>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;
const FS_CLIENT_SECRET = process.env.FS_CLIENT_SECRET;
const FS_CLIENT_ID = process.env.FS_CLIENT_ID;

const apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
const sessionIds = new Map();

const foursquareVersion = '20160108';
const foursquareCategories = {
    food: 'food',
    drinks: 'drinks',
    coffee: 'coffee',
    shops: 'shops',
    arts: 'arts',
    topPicks: 'topPicks',
};
const defaultCategory = foursquareCategories.topPicks;
var suggestionLimit = 3;
var closestFirst = 0;

const actionFindVenue = 'findVenue';
const intentFindVenue = 'FindVenue';

function processEvent(event) {
    var sender = event.sender.id.toString();

    if ((event.message && event.message.text) || (event.message && event.message.attachments) || (event.postback && event.postback.payload)) {

        var text = event.message ? event.message.text : event.postback.payload;
        var attachments = event.message.attachments;
        console.log('Attachments: ', attachments);
        /*if (isDefined(attachments)) {
            if (isDefined(attachments[0].payload) && isDefined(attachments[0].payload.coordinates)) {
                if (isDefined(attachments[0].payload.coordinates.lat) && isDefined(attachments[0].payload.coordinates.long)) {
                    text = attachments[0].payload.coordinates.lat.concat(', ', attachments[0].payload.coordinates.long);
                }
            }
        }*/

        if (!isDefined(text)) {
            console.log('Attachments only!');
        }

        // Handle a message from this sender

        if (!sessionIds.has(sender)) {
            sessionIds.set(sender, uuid.v1());
        }

        console.log("Text:", text);

        let apiaiRequest = apiAiService.textRequest(text,
            {
                sessionId: sessionIds.get(sender)
            });

        apiaiRequest.on('response', (response) => {
            if (isDefined(response.result)) {
                let responseText = response.result.fulfillment.speech;
                let responseData = response.result.fulfillment.data;
                var action = response.result.action;
                var intentName = response.result.metadata.intentName;
                var parameters = response.result.parameters;

                console.log(action);

                if (isDefined(responseData) && isDefined(responseData.facebook)) {
                    if (!Array.isArray(responseData.facebook)) {
                        try {
                            console.log('Response as formatted message');
                            sendFBMessage(sender, responseData.facebook);
                        } catch (err) {
                            sendFBMessage(sender, {text: err.message});
                        }
                    } else {
                        async.eachSeries(responseData.facebook, (facebookMessage, callback) => {
                            try {
                                if (facebookMessage.sender_action) {
                                    console.log('Response as sender action');
                                    sendFBSenderAction(sender, facebookMessage.sender_action, callback);
                                }
                                else {
                                    console.log('Response as formatted message');
                                    sendFBMessage(sender, facebookMessage, callback);
                                }
                            } catch (err) {
                                sendFBMessage(sender, {text: err.message}, callback);
                            }
                        });
                    }
                } else if (isDefined(responseText)) {
                    textResponse(responseText, sender);
                } else if (isDefined(action) && isDefined(intentName)) {

                    if (action === actionFindVenue && intentName == intentFindVenue) {
                        if (isDefined(parameters)) {
                            findVenue(parameters, (foursquareResponse) => {
                                if (isDefined(foursquareResponse)) {
                                    console.log('Response is defined');
                                    sendFBCardMessage(sender, formatVenueData(foursquareResponse));
                                } else {
                                    textResponse('Please specify a location.', sender);
                                }
                            });
                        }
                    }
                }

            }
        });

        apiaiRequest.on('error', (error) => console.error(error));
        apiaiRequest.end();
    }
}

function processLocation(event, callback) {
    if (isDefined(event.message.attachments)) {
        console.log('processing location');
        callback(event);
    }
}

function textResponse(str, sender) {
    console.log('Response as text message');
        // facebook API limit for text length is 320,
        // so we must split message if needed
    var splittedText = splitResponse(str);

    async.eachSeries(splittedText, (textPart, callback) => {
        sendFBMessage(sender, {text: textPart}, callback);
    });
}

function splitResponse(str) {
    if (str.length <= 320) {
        return [str];
    }

    return chunkString(str, 300);
}

function chunkString(s, len) {
    var curr = len, prev = 0;

    var output = [];

    while (s[curr]) {
        if (s[curr++] == ' ') {
            output.push(s.substring(prev, curr));
            prev = curr;
            curr += len;
        }
        else {
            var currReverse = curr;
            do {
                if (s.substring(currReverse - 1, currReverse) == ' ') {
                    output.push(s.substring(prev, currReverse));
                    prev = currReverse;
                    curr = currReverse + len;
                    break;
                }
                currReverse--;
            } while (currReverse > prev);
        }
    }
    output.push(s.substr(prev));
    return output;
}

function sendFBMessage(sender, messageData, callback) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: sender},
            message: messageData
        }
    }, (error, response, body) => {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }

        if (callback) {
            callback();
        }
    });
}

function sendFBCardMessage (sender, messageData, callback) {
    console.log('Sending card message: ');

    var cardOptions = {
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: sender},
            message: {
                'attachment': {
                    'type':'template',
                    'payload': {
                      'template_type':'generic',
                      'elements':[]
                    }
                }
            }
        }
    };

    for (let i = 0; i < suggestionLimit; i++) {
        cardOptions.json.message.attachment.payload.elements.push(messageData[i]);
    }

    request(cardOptions, (error, response, body) => {
        if (error) {
            console.log('Error sending card: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }

        if (callback) {
            callback();
        }
    });
}

function sendFBSenderAction(sender, action, callback) {
    setTimeout(() => {
        request({
            url: 'https://graph.facebook.com/v2.6/me/messages',
            qs: {access_token: FB_PAGE_ACCESS_TOKEN},
            method: 'POST',
            json: {
                recipient: {id: sender},
                sender_action: action
            }
        }, (error, response, body) => {
            if (error) {
                console.log('Error sending action: ', error);
            } else if (response.body.error) {
                console.log('Error: ', response.body.error);
            }
            if (callback) {
                callback();
            }
        });
    }, 1000);
}

function doSubscribeRequest() {
    request({
            method: 'POST',
            uri: "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=" + FB_PAGE_ACCESS_TOKEN
        },
        (error, response, body) => {
            if (error) {
                console.error('Error while subscription: ', error);
            } else {
                console.log('Subscription result: ', response.body);
            }
        });
}

function isDefined(obj) {
    if (typeof obj == 'undefined') {
        return false;
    }

    if (!obj) {
        return false;
    }

    return obj != null;
}

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        var data = JSONbig.parse(req.body);

        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                        if (event.message && event.message.attachments &&
                            event.message.attachments.length > 0) {
                            console.log(event.message.attachments);
                            processLocation(event, (locEvent) => {
                                processEvent(locEvent);
                            });
                        } else if (event.message && !event.message.is_echo ||
                            event.postback && event.postback.payload) {
                            console.log('processing event');
                            processEvent(event);
                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

doSubscribeRequest();

function formatVenueData(raw) {
    var items = raw.response.groups[0].items;
    var venues = [];
    var j = 0;

    if (isDefined(items)) {
        for (let i = 0; i < suggestionLimit; i++) {
            var venue = items[i].venue;
            var url = venue.url;

            var formatted = {};
            formatted.title = venue.name;

            if (isDefined(venue.hours) && isDefined(venue.hours.status)) {
                formatted.subtitle = venue.hours.status;
            } else {
                formatted.subtitle = '';
            }

            formatted.buttons = [];
            j = 0;

            formatted.buttons[j] = {
                type: 'web_url',
                title: 'View Website',
            };

            if (isDefined(url)) {
                formatted.buttons[j].url = url;
                j++;
            } else {
                formatted.buttons[j].url = 'http://foursquare.com/v/'.concat(venue.id);
                j++;
            }

            formatted.buttons[j] = {
                type: 'web_url',
            };
            if (isDefined(venue.location) && isDefined(venue.location.formattedAddress && venue.location.formattedAddress.length > 1)) {
                formatted.buttons[j].title = venue.location.formattedAddress[0].concat(', ', venue.location.formattedAddress[1]);
            } else {
                formatted.buttons[j].title = venue.location.city;
            }
            formatted.buttons[j].url = 'http://maps.google.com/?q='.concat(formatted.buttons[j].title);

            venues.push(formatted);
        }
    }
    return venues;
}

function formatGETOptions(parameters) {

    var venueType = defaultCategory;

    if (isDefined(parameters.venueType)) {
        venueType = parameters.venueType;
    }

    console.log(defaultCategory);
    console.log('Address: ', isDefined(parameters.location));
    console.log('Coordinates: ', isDefined(parameters.coordinates));
    console.log('Venue: ', isDefined(parameters.venueType));

    var options = {
        method: 'GET',
        url: 'http://api.foursquare.com/v2/venues/explore',
        qs: {
            client_id: FS_CLIENT_ID,
            client_secret: FS_CLIENT_SECRET,
            v: foursquareVersion,
            m: 'foursquare',
            section: venueType,
            limit: suggestionLimit,
            sortByDistance: closestFirst,
        },
        venuePhotos: 1,
        json: true,
    };

    console.log('VenueType: ', venueType);
    console.log('Venue: ', options.qs.section);

    if (isDefined(parameters.location)) {
        console.log('Location defined');
        if (isDefined(parameters.location.location)) { //location as address
            options.qs.near = parameters.location.location;
        }
    } else if (isDefined(parameters.coordinates)) { //location as coordinates
        console.log('Coordinates defined');
        let lat = parameters.coordinates.lat;
        let long = parameters.coordinates.long;
        console.log(typeof(lat));
        options.qs.ll = lat.toString().concat(', ', long.toString());
    } else {
        return null;
    }

    console.log('Location: ', options.qs.ll);

    return options;
}

function findVenue(parameters, callback) {

    var options = formatGETOptions(parameters);

    if (isDefined(options)) {
        request(options, (error, res, body) => {
            if (error) {
                console.error('GET Error: ', error);
            } else {
                callback(body);
            }
        });
    } else {
        callback(null);
    }
}<commit_msg>no message<commit_after>'use strict';

const apiai = require('apiai');
const express = require('express');
const bodyParser = require('body-parser');
const uuid = require('node-uuid');
const request = require('request');
const JSONbig = require('json-bigint');
const async = require('async');

const REST_PORT = (process.env.PORT || 5000);
const APIAI_ACCESS_TOKEN = process.env.APIAI_ACCESS_TOKEN;
const APIAI_LANG = process.env.APIAI_LANG || 'en';
const FB_VERIFY_TOKEN = process.env.FB_VERIFY_TOKEN;
const FB_PAGE_ACCESS_TOKEN = process.env.FB_PAGE_ACCESS_TOKEN;
const FS_CLIENT_SECRET = process.env.FS_CLIENT_SECRET;
const FS_CLIENT_ID = process.env.FS_CLIENT_ID;

const apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
const sessionIds = new Map();

const foursquareVersion = '20160108';
const foursquareCategories = {
    food: 'food',
    drinks: 'drinks',
    coffee: 'coffee',
    shops: 'shops',
    arts: 'arts',
    topPicks: 'topPicks',
};
const defaultCategory = foursquareCategories.topPicks;
var suggestionLimit = 3;
var closestFirst = 0;

const actionFindVenue = 'findVenue';
const intentFindVenue = 'FindVenue';

function processEvent(event) {
    var sender = event.sender.id.toString();

    if ((event.message && event.message.text) || (event.message && event.message.attachments) || (event.postback && event.postback.payload)) {

        var text = event.message ? event.message.text : event.postback.payload;
        var attachments = event.message.attachments;
        console.log('Attachments: ', attachments);

        if (!isDefined(text) && attachments.type === 'location') {
            console.log('Attachments only!');
            let lat = attachments.coordinates.lat;
            let long = attachments.coordinates.long;
            console.log(typeof(lat));
            text = 'Found coordinates';
        }

        // Handle a message from this sender

        if (!sessionIds.has(sender)) {
            sessionIds.set(sender, uuid.v1());
        }

        console.log("Text:", text);

        let apiaiRequest = apiAiService.textRequest(text,
            {
                sessionId: sessionIds.get(sender)
            });

        apiaiRequest.on('response', (response) => {
            if (isDefined(response.result)) {
                let responseText = response.result.fulfillment.speech;
                let responseData = response.result.fulfillment.data;
                var action = response.result.action;
                var intentName = response.result.metadata.intentName;
                var parameters = response.result.parameters;

                console.log(action);

                if (isDefined(responseData) && isDefined(responseData.facebook)) {
                    if (!Array.isArray(responseData.facebook)) {
                        try {
                            console.log('Response as formatted message');
                            sendFBMessage(sender, responseData.facebook);
                        } catch (err) {
                            sendFBMessage(sender, {text: err.message});
                        }
                    } else {
                        async.eachSeries(responseData.facebook, (facebookMessage, callback) => {
                            try {
                                if (facebookMessage.sender_action) {
                                    console.log('Response as sender action');
                                    sendFBSenderAction(sender, facebookMessage.sender_action, callback);
                                }
                                else {
                                    console.log('Response as formatted message');
                                    sendFBMessage(sender, facebookMessage, callback);
                                }
                            } catch (err) {
                                sendFBMessage(sender, {text: err.message}, callback);
                            }
                        });
                    }
                } else if (isDefined(responseText)) {
                    textResponse(responseText, sender);
                } else if (isDefined(action) && isDefined(intentName)) {

                    if (action === actionFindVenue && intentName == intentFindVenue) {
                        if (isDefined(parameters)) {
                            findVenue(parameters, (foursquareResponse) => {
                                if (isDefined(foursquareResponse)) {
                                    console.log('Response is defined');
                                    sendFBCardMessage(sender, formatVenueData(foursquareResponse));
                                } else {
                                    textResponse('Please specify a location.', sender);
                                }
                            });
                        }
                    }
                }

            }
        });

        apiaiRequest.on('error', (error) => console.error(error));
        apiaiRequest.end();
    }
}

function processLocation(event, callback) {
    if (isDefined(event.message.attachments)) {
        console.log('processing location');
        callback(event);
    }
}

function textResponse(str, sender) {
    console.log('Response as text message');
        // facebook API limit for text length is 320,
        // so we must split message if needed
    var splittedText = splitResponse(str);

    async.eachSeries(splittedText, (textPart, callback) => {
        sendFBMessage(sender, {text: textPart}, callback);
    });
}

function splitResponse(str) {
    if (str.length <= 320) {
        return [str];
    }

    return chunkString(str, 300);
}

function chunkString(s, len) {
    var curr = len, prev = 0;

    var output = [];

    while (s[curr]) {
        if (s[curr++] == ' ') {
            output.push(s.substring(prev, curr));
            prev = curr;
            curr += len;
        }
        else {
            var currReverse = curr;
            do {
                if (s.substring(currReverse - 1, currReverse) == ' ') {
                    output.push(s.substring(prev, currReverse));
                    prev = currReverse;
                    curr = currReverse + len;
                    break;
                }
                currReverse--;
            } while (currReverse > prev);
        }
    }
    output.push(s.substr(prev));
    return output;
}

function sendFBMessage(sender, messageData, callback) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: sender},
            message: messageData
        }
    }, (error, response, body) => {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }

        if (callback) {
            callback();
        }
    });
}

function sendFBCardMessage (sender, messageData, callback) {
    console.log('Sending card message: ');

    var cardOptions = {
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: FB_PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: sender},
            message: {
                'attachment': {
                    'type':'template',
                    'payload': {
                      'template_type':'generic',
                      'elements':[]
                    }
                }
            }
        }
    };

    for (let i = 0; i < suggestionLimit; i++) {
        cardOptions.json.message.attachment.payload.elements.push(messageData[i]);
    }

    request(cardOptions, (error, response, body) => {
        if (error) {
            console.log('Error sending card: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }

        if (callback) {
            callback();
        }
    });
}

function sendFBSenderAction(sender, action, callback) {
    setTimeout(() => {
        request({
            url: 'https://graph.facebook.com/v2.6/me/messages',
            qs: {access_token: FB_PAGE_ACCESS_TOKEN},
            method: 'POST',
            json: {
                recipient: {id: sender},
                sender_action: action
            }
        }, (error, response, body) => {
            if (error) {
                console.log('Error sending action: ', error);
            } else if (response.body.error) {
                console.log('Error: ', response.body.error);
            }
            if (callback) {
                callback();
            }
        });
    }, 1000);
}

function doSubscribeRequest() {
    request({
            method: 'POST',
            uri: "https://graph.facebook.com/v2.6/me/subscribed_apps?access_token=" + FB_PAGE_ACCESS_TOKEN
        },
        (error, response, body) => {
            if (error) {
                console.error('Error while subscription: ', error);
            } else {
                console.log('Subscription result: ', response.body);
            }
        });
}

function isDefined(obj) {
    if (typeof obj == 'undefined') {
        return false;
    }

    if (!obj) {
        return false;
    }

    return obj != null;
}

const app = express();

app.use(bodyParser.text({type: 'application/json'}));

app.get('/webhook/', (req, res) => {
    if (req.query['hub.verify_token'] == FB_VERIFY_TOKEN) {
        res.send(req.query['hub.challenge']);

        setTimeout(() => {
            doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        var data = JSONbig.parse(req.body);

        if (data.entry) {
            let entries = data.entry;
            entries.forEach((entry) => {
                let messaging_events = entry.messaging;
                if (messaging_events) {
                    messaging_events.forEach((event) => {
                        if (event.message && event.message.attachments &&
                            event.message.attachments.length > 0) {
                            console.log(event.message.attachments);
                            processLocation(event, (locEvent) => {
                                processEvent(locEvent);
                            });
                        } else if (event.message && !event.message.is_echo ||
                            event.postback && event.postback.payload) {
                            console.log('processing event');
                            processEvent(event);
                        }
                    });
                }
            });
        }

        return res.status(200).json({
            status: "ok"
        });
    } catch (err) {
        return res.status(400).json({
            status: "error",
            error: err
        });
    }

});

app.listen(REST_PORT, () => {
    console.log('Rest service ready on port ' + REST_PORT);
});

doSubscribeRequest();

function formatVenueData(raw) {
    var items = raw.response.groups[0].items;
    var venues = [];
    var j = 0;

    if (isDefined(items)) {
        for (let i = 0; i < suggestionLimit; i++) {
            var venue = items[i].venue;
            var url = venue.url;

            var formatted = {};
            formatted.title = venue.name;

            if (isDefined(venue.hours) && isDefined(venue.hours.status)) {
                formatted.subtitle = venue.hours.status;
            } else {
                formatted.subtitle = '';
            }

            formatted.buttons = [];
            j = 0;

            formatted.buttons[j] = {
                type: 'web_url',
                title: 'View Website',
            };

            if (isDefined(url)) {
                formatted.buttons[j].url = url;
                j++;
            } else {
                formatted.buttons[j].url = 'http://foursquare.com/v/'.concat(venue.id);
                j++;
            }

            formatted.buttons[j] = {
                type: 'web_url',
            };
            if (isDefined(venue.location) && isDefined(venue.location.formattedAddress && venue.location.formattedAddress.length > 1)) {
                formatted.buttons[j].title = venue.location.formattedAddress[0].concat(', ', venue.location.formattedAddress[1]);
            } else {
                formatted.buttons[j].title = venue.location.city;
            }
            formatted.buttons[j].url = 'http://maps.google.com/?q='.concat(formatted.buttons[j].title);

            venues.push(formatted);
        }
    }
    return venues;
}

function formatGETOptions(parameters) {

    var venueType = defaultCategory;

    if (isDefined(parameters.venueType)) {
        venueType = parameters.venueType;
    }

    console.log(defaultCategory);
    console.log('Address: ', isDefined(parameters.location));
    console.log('Coordinates: ', isDefined(parameters.coordinates));
    console.log('Venue: ', isDefined(parameters.venueType));

    var options = {
        method: 'GET',
        url: 'http://api.foursquare.com/v2/venues/explore',
        qs: {
            client_id: FS_CLIENT_ID,
            client_secret: FS_CLIENT_SECRET,
            v: foursquareVersion,
            m: 'foursquare',
            section: venueType,
            limit: suggestionLimit,
            sortByDistance: closestFirst,
        },
        venuePhotos: 1,
        json: true,
    };

    console.log('VenueType: ', venueType);
    console.log('Venue: ', options.qs.section);

    if (isDefined(parameters.location)) {
        console.log('Location defined');
        if (isDefined(parameters.location.location)) { //location as address
            options.qs.near = parameters.location.location;
        }
    } else if (isDefined(parameters.coordinates)) { //location as coordinates
        console.log('Coordinates defined');
        let lat = parameters.coordinates.lat;
        let long = parameters.coordinates.long;
        console.log(typeof(lat));
        options.qs.ll = lat.toString().concat(', ', long.toString());
    } else {
        return null;
    }

    console.log('Location: ', options.qs.ll);

    return options;
}

function findVenue(parameters, callback) {

    var options = formatGETOptions(parameters);

    if (isDefined(options)) {
        request(options, (error, res, body) => {
            if (error) {
                console.error('GET Error: ', error);
            } else {
                callback(body);
            }
        });
    } else {
        callback(null);
    }
}<|endoftext|>


<commit_before>var allRows;

function notEqual(a, b){
  if( a instanceof Date || b instanceof Date ){
    return a.getTime() != b.getTime();
  } else {
    return a != b;
  }
}

function unique(a, b){
  if( a instanceof Array ){
    var s = d3.set(a)
    s.add(b)
    return s.values();
  } else {
    return d3.set([a, b]).values();
  }
}

function allegationReducer(complaint, allegation){
  var newObj = {};
  for (key in complaint){
    if( complaint.hasOwnProperty(key) ){
      var complaintVal = complaint[key];
      var allegationVal = allegation[key];
      if( notEqual(complaintVal, allegationVal) ){
          newObj[key] = unique(complaintVal, allegationVal);
      } else {
        newObj[key] = complaint[key];
      }
    }
  }
  return newObj;
}

function allegationsToComplaints(rows){
  var complaintGrouper = d3.nest()
    .key(function (d){ return d.id; })
    .rollup(function(allegations){
      var complaint = allegations.reduce(allegationReducer);
      complaint['allegations'] = allegations;
      return complaint;
    });
  return complaintGrouper.map(rows, d3.map).values();
}

function uniqueOfficerComplaints(rows){
  var newSet = [];
  var grouper = d3.nest()
    .key(function (d){ return d.officerIdentifier; })
    .key(function (d){ return d.id; });
  var officerComplaintMap = grouper.map(rows, d3.map);
  officerComplaintMap.forEach(function(offId, complaints){
    newSet.push({
      officerId: offId,
      complaintCount: complaints.keys().length,
      values: complaints
    });
  });
  return newSet;
}

function raceKey( value ) {
  if( !value ){
    value = "";
  }
  return {
    "Unknown": "Unknown",
    "Black": "Black",
    "": "Unknown",
    "Hispanic": "Hispanic",
    "White": "White",
    "Bi-racial": "Other",
    "White ": "White",
    "black": "Black",
    "B": "Black",
    "Asian": "Asian",
    "Other": "Other",
    "Polynesian": "Asian",
  }[value];
};

function race(k){
  return function(d){
    return raceKey(d[k]);
  };
}

function uniqueResidentProxy(d){
   return [ d.residentAge, "year old", d.residentRace, d.residentSex ].join(" ");
}

function uniqueComplaintAboutOfficerByResidentProxy(d){
   return [
     d.residentAge,
     "year old",
     d.residentRace,
     d.residentSex,
     "filed",
     d.id,
     "about",
     d.officerIdentifier
       ].join(" ");
}

function raceMatrix(config, data){

  var complaints = d3.nest()
    .key(uniqueComplaintAboutOfficerByResidentProxy)
    .rollup(function (group){
      var obj = {};
      [ 'residentAge', 'residentSex', 'officerAge',
        'officerSex', 'officerYearsOfService',
        ].map(function(k){
          obj[k] = group[0][k];
        });
      [ 'residentRace', 'officerRace',
        ].map(function(k){
          obj[k] = raceKey(group[0][k]);
        });
      obj.allegations = group;
      return obj;
    }).entries(data);

  var totalComplaintCount = complaints.length;
  var counts = d3.nest()
    .key(function(d){
      return d.values.residentRace;
    }).key(function(d){
      return d.values.officerRace;
    }).rollup(function(group){
      return {
        count: group.length,
        percent: ( group.length / totalComplaintCount ),
        complaints: group,
      };
    }).map(complaints, d3.map);

  var officerRaceTotals = d3.nest()
    .key(function(d){ return d.values.officerRace; })
    .rollup(function(group){
      return {
        count: group.length,
        percent: ( group.length / totalComplaintCount ),
      };
    }).map(complaints, d3.map);

  // unique keys for officer axis
  var allOfficerRaceKeys = officerRaceTotals.keys();

  // get resident race totals
  counts.keys().forEach(function(resRace){
      var total = 0;
      var subgroups = counts.get(resRace);
      subgroups.values().map(function(offRace){ total += offRace.count; });

      // add missing races, but only the unique keys of the corresponding axis
      allOfficerRaceKeys.forEach(function(officerRace){
        if( !subgroups.get(officerRace) ){
          subgroups.set(officerRace, {})
        }
      });
      subgroups.count = total;
      subgroups.percent = ( total / totalComplaintCount );
    });

  counts.officerRaceTotals = officerRaceTotals;
  return counts;
}

function officerComplaintsCount(config, data){
  data = uniqueOfficerComplaints(data);
  var counts = d3.nest()
    .key( function (d){
      return d.complaintCount;
    }).rollup( function (values){
      return values.length;
    }).entries(data);
  return counts.map(function(e){
    var obj = {};
    var n = e.key;
    obj['label'] = "Officers with " + ( n > 1 ? n+" complaints" : n+" complaint" );
    obj['count'] = n;
    obj[config.y] = e.values;
    return obj;
  });
}

var experienceBuckets = d3.scale.quantize()
  .domain([2.5, 5.5, 10.5])
  .range([
      '0-2 years',
      '3-5 years',
      '6-10 years',
      '10+ years',
      ]);

var currentYear = 2015;
var defaultNullValue = "NULL";

function translate(x, y){
  return "translate(" + x + "," + y + ")";
}

function mergeMaps(a, b){
  b.forEach(function(k, v){
    a.set(k, v);
  });
}

function nullify(value){
  if (value === defaultNullValue){
    return null;
  } else {
    return value
  }
}

function addMissingYears(dataMap){
  // add missing years to the map, so we know they are empty
  var year0 = d3.min(dataMap.keys());
  var allYears = d3.range(year0, currentYear);
  allYears.forEach(function(yr){
    if( !dataMap.has(yr) ){
      dataMap.set(
        yr, {
          year: yr,
          count: 0,
          incidents: [],
      });
    }
  });
}

function addOtherCategory(data){
  var threshold = .006;
  var small_list = [];
  var total = data.map(function (g){
    return g.count;
  }).reduce(function (a,b) {
    return a + b;
  });
  var otherTotal = 0;

  data.forEach(function(d, i) {
    if(d.count / total < threshold){
      small_list.push(i);
      otherTotal = otherTotal + d.count;
    }
  });

  data.push({
    type: "Other",
    count: otherTotal,
    groups: small_list.map(function(i){
      return data[i];
    })
  })

  var removed_count = 0;
  small_list.forEach(function(i){
    i -= removed_count;
    data.splice(i, 1);
    removed_count += 1;
  });
}

function last12Months(rows, config){
  // offset today by 12 d3-defined months in the past
  var latestDate = d3.max(rows, function(d){ return d.date; })
  var startDate = d3.time.month.offset(latestDate, -12);
  config.dateSpan = [startDate, latestDate];
  return rows.filter(function(r){
    return startDate < r.date;
  });
}

var dateTimeFormat = d3.time.format("%Y-%m-%d %H:%M:%S");
var niceMonthYearFormat = d3.time.format('%b %Y');
var dateTimeKey = "occurredDate";
function parseDate(dateTimeString){
  return dateTimeString ? dateTimeFormat.parse(dateTimeString) : null;
}

function parseData(rows){
  // parses dates and nulls from the raw csv
  rows.forEach(function(r){
    var dateString = nullify(r[dateTimeKey]);
    r.date = parseDate(dateString);
  });
  rows = rows.filter(function(d){
    return d.date;
  });
  return rows;
}

function uniqueForKeys(){
  // takes a list of key strings to filter a set of raw incidents
  // concatenates the values of the given keys to provide a unique key
  // for example:
  //    uniqueForKeys('id', 'shift', 'beat')
  // returns an array of objects representing each unique
  // combination of the values of those columns
   //   returns [
   //     {id:1, shift: 'a', beat: 'b'},
   //     {id:1, shift: 'c', beat: 'b'},
   //     {id:2, shift: 'a', beat: 'b'},
   // ]
  function concatValues(values){
    var separator = '-';
    var result = '';
    values.forEach(function(val){
      result += (separator + val);
    });
    return result;
  }
  var keys = Array.prototype.slice.call(arguments);
  var grouper = d3.nest()
    .key(function (d){
      var values = keys.map(function(k){ return d[k]; });
      return concatValues(values);
    }).rollup(function(leaves){
      // each 'leaf' has the same values for the keys
      var datum = {};
      keys.forEach(function(k){
        datum[k] = leaves[0][k];
      });
      return datum;
    })
    return function(unfilteredRows){
      return grouper.map(unfilteredRows, d3.map)
        .values();
    };
}

function structureData(parsed_rows, config){
  // restructures csv data into data than can be used to draw a chart

  // create a grouping machine that groups by key function
  var data_grouper = d3.nest()
    .key(config.keyFunc)
    .rollup(function(leaves){
      var datum = {};
      datum[config.y] = config.yFunc(leaves);
      datum[config.x] = config.xFunc(leaves);
      datum['incidents'] = leaves;
      return datum;
    });

  // use the parsed data and the grouping machine to create a
  // simple key value store (aka "map") with years as keys
  var data = data_grouper.map(parsed_rows, d3.map);

  if( config.dataMapAdjust ){
    config.dataMapAdjust(data);
  }

  if( config.dontFlatten ){
    return data;
  }

  if( config.removeBlankX ){
    data.remove("");
  }

  // return data structured for a chart
  var structured_data = data.values();
  if( config.sortWith ){
    var mapped = structured_data.map(function(d, i){
      return { index: i, value: config.sortWith(d) };
    });
    mapped.sort(function(a,b){
      return +(a.value > b.value) || +(a.value === b.value) - 1;
    });
    structured_data = mapped.map(function(n){
      return structured_data[n.index];
    });
  }
  if( config.addOther ){
    addOtherCategory(structured_data)
  }
  return structured_data;
}

function drawChart(rows, config){

  // filter rows if necessary
  if( config.filter ){
    rows = config.filter(rows, config);
  }

  // structure data for the particular chart
  if( config.dataFunc ){
    var data = config.dataFunc(config, rows);
  } else {
    var data = structureData(rows, config);
  }
  if( !config.dateSpan ){
    config.dateSpan = allRows.dateSpan;
  }

  if( !config.hideDate ){
    // add the date interval for this chart's data
    $(config.brick).find('.brick-titleblock > h4').append(
      ' ' +
        '' +
          niceMonthYearFormat(config.dateSpan[0]) +
        ' ' +
        '' +
          '—' +
        ' ' +
        '' +
          niceMonthYearFormat(config.dateSpan[1]) +
        '' +
      '');
  }
  // get the correct function for drawing this chart
  drawingFunction = drawFuncs[config.chartType];

  // if we have no chart block in the database, just make the brick
  if(config.noTemplate){
    var brick = d3.select('[role=main]')
      .append('div').attr("class", "brick");
    brick.append("h4").attr("class", "brick-title")
      .text(config.title);
    config.parent = brick.append("div").attr("class", config.parent)[0][0];
  }

  // run the function to draw the chart
  drawingFunction(config, data);
}

drawFuncs = {
  'lineChart': lineChart,
  'percent': basicPercent,
  'flagHistogram': flagHistogram,
  'mountainHistogram': mountainHistogram,
  'symmetricalFlags': symmetricalFlags,
  'matrix': matrixChart,
}
<commit_msg>adds uniqueForKeysInLast12Months filter<commit_after>var allRows;

function notEqual(a, b){
  if( a instanceof Date || b instanceof Date ){
    return a.getTime() != b.getTime();
  } else {
    return a != b;
  }
}

function unique(a, b){
  if( a instanceof Array ){
    var s = d3.set(a)
    s.add(b)
    return s.values();
  } else {
    return d3.set([a, b]).values();
  }
}

function allegationReducer(complaint, allegation){
  var newObj = {};
  for (key in complaint){
    if( complaint.hasOwnProperty(key) ){
      var complaintVal = complaint[key];
      var allegationVal = allegation[key];
      if( notEqual(complaintVal, allegationVal) ){
          newObj[key] = unique(complaintVal, allegationVal);
      } else {
        newObj[key] = complaint[key];
      }
    }
  }
  return newObj;
}

function allegationsToComplaints(rows){
  var complaintGrouper = d3.nest()
    .key(function (d){ return d.id; })
    .rollup(function(allegations){
      var complaint = allegations.reduce(allegationReducer);
      complaint['allegations'] = allegations;
      return complaint;
    });
  return complaintGrouper.map(rows, d3.map).values();
}

function uniqueOfficerComplaints(rows){
  var newSet = [];
  var grouper = d3.nest()
    .key(function (d){ return d.officerIdentifier; })
    .key(function (d){ return d.id; });
  var officerComplaintMap = grouper.map(rows, d3.map);
  officerComplaintMap.forEach(function(offId, complaints){
    newSet.push({
      officerId: offId,
      complaintCount: complaints.keys().length,
      values: complaints
    });
  });
  return newSet;
}

function raceKey( value ) {
  if( !value ){
    value = "";
  }
  return {
    "Unknown": "Unknown",
    "Black": "Black",
    "": "Unknown",
    "Hispanic": "Hispanic",
    "White": "White",
    "Bi-racial": "Other",
    "White ": "White",
    "black": "Black",
    "B": "Black",
    "Asian": "Asian",
    "Other": "Other",
    "Polynesian": "Asian",
  }[value];
};

function race(k){
  return function(d){
    return raceKey(d[k]);
  };
}

function uniqueResidentProxy(d){
   return [ d.residentAge, "year old", d.residentRace, d.residentSex ].join(" ");
}

function uniqueComplaintAboutOfficerByResidentProxy(d){
   return [
     d.residentAge,
     "year old",
     d.residentRace,
     d.residentSex,
     "filed",
     d.id,
     "about",
     d.officerIdentifier
       ].join(" ");
}

function raceMatrix(config, data){

  var complaints = d3.nest()
    .key(uniqueComplaintAboutOfficerByResidentProxy)
    .rollup(function (group){
      var obj = {};
      [ 'residentAge', 'residentSex', 'officerAge',
        'officerSex', 'officerYearsOfService',
        ].map(function(k){
          obj[k] = group[0][k];
        });
      [ 'residentRace', 'officerRace',
        ].map(function(k){
          obj[k] = raceKey(group[0][k]);
        });
      obj.allegations = group;
      return obj;
    }).entries(data);

  var totalComplaintCount = complaints.length;
  var counts = d3.nest()
    .key(function(d){
      return d.values.residentRace;
    }).key(function(d){
      return d.values.officerRace;
    }).rollup(function(group){
      return {
        count: group.length,
        percent: ( group.length / totalComplaintCount ),
        complaints: group,
      };
    }).map(complaints, d3.map);

  var officerRaceTotals = d3.nest()
    .key(function(d){ return d.values.officerRace; })
    .rollup(function(group){
      return {
        count: group.length,
        percent: ( group.length / totalComplaintCount ),
      };
    }).map(complaints, d3.map);

  // unique keys for officer axis
  var allOfficerRaceKeys = officerRaceTotals.keys();

  // get resident race totals
  counts.keys().forEach(function(resRace){
      var total = 0;
      var subgroups = counts.get(resRace);
      subgroups.values().map(function(offRace){ total += offRace.count; });

      // add missing races, but only the unique keys of the corresponding axis
      allOfficerRaceKeys.forEach(function(officerRace){
        if( !subgroups.get(officerRace) ){
          subgroups.set(officerRace, {})
        }
      });
      subgroups.count = total;
      subgroups.percent = ( total / totalComplaintCount );
    });

  counts.officerRaceTotals = officerRaceTotals;
  return counts;
}

function officerComplaintsCount(config, data){
  data = uniqueOfficerComplaints(data);
  var counts = d3.nest()
    .key( function (d){
      return d.complaintCount;
    }).rollup( function (values){
      return values.length;
    }).entries(data);
  return counts.map(function(e){
    var obj = {};
    var n = e.key;
    obj['label'] = "Officers with " + ( n > 1 ? n+" complaints" : n+" complaint" );
    obj['count'] = n;
    obj[config.y] = e.values;
    return obj;
  });
}

var experienceBuckets = d3.scale.quantize()
  .domain([2.5, 5.5, 10.5])
  .range([
      '0-2 years',
      '3-5 years',
      '6-10 years',
      '10+ years',
      ]);

var currentYear = 2015;
var defaultNullValue = "NULL";

function translate(x, y){
  return "translate(" + x + "," + y + ")";
}

function mergeMaps(a, b){
  b.forEach(function(k, v){
    a.set(k, v);
  });
}

function nullify(value){
  if (value === defaultNullValue){
    return null;
  } else {
    return value
  }
}

function addMissingYears(dataMap){
  // add missing years to the map, so we know they are empty
  var year0 = d3.min(dataMap.keys());
  var allYears = d3.range(year0, currentYear);
  allYears.forEach(function(yr){
    if( !dataMap.has(yr) ){
      dataMap.set(
        yr, {
          year: yr,
          count: 0,
          incidents: [],
      });
    }
  });
}

function addOtherCategory(data){
  var threshold = .006;
  var small_list = [];
  var total = data.map(function (g){
    return g.count;
  }).reduce(function (a,b) {
    return a + b;
  });
  var otherTotal = 0;

  data.forEach(function(d, i) {
    if(d.count / total < threshold){
      small_list.push(i);
      otherTotal = otherTotal + d.count;
    }
  });

  data.push({
    type: "Other",
    count: otherTotal,
    groups: small_list.map(function(i){
      return data[i];
    })
  })

  var removed_count = 0;
  small_list.forEach(function(i){
    i -= removed_count;
    data.splice(i, 1);
    removed_count += 1;
  });
}

function last12Months(rows, config){
  // offset today by 12 d3-defined months in the past
  var latestDate = d3.max(rows, function(d){ return d.date; })
  var startDate = d3.time.month.offset(latestDate, -12);
  config.dateSpan = [startDate, latestDate];
  return rows.filter(function(r){
    return startDate < r.date;
  });
}

var dateTimeFormat = d3.time.format("%Y-%m-%d %H:%M:%S");
var niceMonthYearFormat = d3.time.format('%b %Y');
var dateTimeKey = "occurredDate";
function parseDate(dateTimeString){
  return dateTimeString ? dateTimeFormat.parse(dateTimeString) : null;
}

function parseData(rows){
  // parses dates and nulls from the raw csv
  rows.forEach(function(r){
    var dateString = nullify(r[dateTimeKey]);
    r.date = parseDate(dateString);
  });
  rows = rows.filter(function(d){
    return d.date;
  });
  return rows;
}

function uniqueForKeys(){
  // takes a list of key strings to filter a set of raw incidents
  // concatenates the values of the given keys to provide a unique key
  // for example:
  //    uniqueForKeys('id', 'shift', 'beat')
  // returns an array of objects representing each unique
  // combination of the values of those columns
   //   returns [
   //     {id:1, shift: 'a', beat: 'b'},
   //     {id:1, shift: 'c', beat: 'b'},
   //     {id:2, shift: 'a', beat: 'b'},
   // ]
  function concatValues(values){
    var separator = '-';
    var result = '';
    values.forEach(function(val){
      result += (separator + val);
    });
    return result;
  }
  var keys = Array.prototype.slice.call(arguments);
  var grouper = d3.nest()
    .key(function (d){
      var values = keys.map(function(k){ return d[k]; });
      return concatValues(values);
    }).rollup(function(leaves){
      // each 'leaf' has the same values for the keys
      var datum = {};
      keys.forEach(function(k){
        datum[k] = leaves[0][k];
      });
      return datum;
    })
    return function(unfilteredRows){
      return grouper.map(unfilteredRows, d3.map)
        .values();
    };
}

function uniqueForKeysInLast12Months(){
  // takes a list of key strings to filter a set of raw incidents
  // concatenates the values of the given keys to provide a unique key
  // but first prefilters down to the last 12 months
  // for example:
  //    uniqueForKeys('id', 'shift', 'beat')
  var args = Array.prototype.slice.call(arguments);
  var uniqueFilter = uniqueForKeys.apply(uniqueForKeys, args)
  return function(rows, config){
    var prefiltered = last12Months(rows, config);
    return uniqueFilter(prefiltered);
  }
}

function structureData(parsed_rows, config){
  // restructures csv data into data than can be used to draw a chart

  // create a grouping machine that groups by key function
  var data_grouper = d3.nest()
    .key(config.keyFunc)
    .rollup(function(leaves){
      var datum = {};
      datum[config.y] = config.yFunc(leaves);
      datum[config.x] = config.xFunc(leaves);
      datum['incidents'] = leaves;
      return datum;
    });

  // use the parsed data and the grouping machine to create a
  // simple key value store (aka "map") with years as keys
  var data = data_grouper.map(parsed_rows, d3.map);

  if( config.dataMapAdjust ){
    config.dataMapAdjust(data);
  }

  if( config.dontFlatten ){
    return data;
  }

  if( config.removeBlankX ){
    data.remove("");
  }

  // return data structured for a chart
  var structured_data = data.values();
  if( config.sortWith ){
    var mapped = structured_data.map(function(d, i){
      return { index: i, value: config.sortWith(d) };
    });
    mapped.sort(function(a,b){
      return +(a.value > b.value) || +(a.value === b.value) - 1;
    });
    structured_data = mapped.map(function(n){
      return structured_data[n.index];
    });
  }
  if( config.addOther ){
    addOtherCategory(structured_data)
  }
  return structured_data;
}

function drawChart(rows, config){

  // filter rows if necessary
  if( config.filter ){
    rows = config.filter(rows, config);
  }

  // structure data for the particular chart
  if( config.dataFunc ){
    var data = config.dataFunc(config, rows);
  } else {
    var data = structureData(rows, config);
  }
  if( !config.dateSpan ){
    config.dateSpan = allRows.dateSpan;
  }

  if( !config.hideDate ){
    // add the date interval for this chart's data
    $(config.brick).find('.brick-titleblock > h4').append(
      ' ' +
        '' +
          niceMonthYearFormat(config.dateSpan[0]) +
        ' ' +
        '' +
          '—' +
        ' ' +
        '' +
          niceMonthYearFormat(config.dateSpan[1]) +
        '' +
      '');
  }
  // get the correct function for drawing this chart
  drawingFunction = drawFuncs[config.chartType];

  // if we have no chart block in the database, just make the brick
  if(config.noTemplate){
    var brick = d3.select('[role=main]')
      .append('div').attr("class", "brick");
    brick.append("h4").attr("class", "brick-title")
      .text(config.title);
    config.parent = brick.append("div").attr("class", config.parent)[0][0];
  }

  // run the function to draw the chart
  drawingFunction(config, data);
}

drawFuncs = {
  'lineChart': lineChart,
  'percent': basicPercent,
  'flagHistogram': flagHistogram,
  'mountainHistogram': mountainHistogram,
  'symmetricalFlags': symmetricalFlags,
  'matrix': matrixChart,
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2011 Nolan Caudill

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/
/*
 * Facebook-conduit
 * This is a simple script that receives events from a facebook callback and then republishes these events through and emitter.
 * I took Nolan Caudill's flickr-conduit idea and stripped the pieces specific for Flick and replaced them with Facebooks.
 *
 * @author Luiz Lopes (http://twitter.com/theprivileges)
 * @see http://search.npmjs.org/#/flickr-conduit
*/
var EventEmitter, urlParser, http, Conduit, parsePost;

EventEmitter = require('events').EventEmitter;
urlParser = require('url').parse;
http = require('http');

Conduit = function () {
    var emitter;

    // Create new emitter
    emitter = new EventEmitter();
    emitter.setMaxListeners(0);
    this.emitter = emitter;

    this.usersLastSeen = {};
    this.userLastSeenThreshold = 30 * 1000; // 5 minutes (since that's the lease length)
};

exports.Conduit = Conduit;

// Recevies parsed URL object and returns true or false
Conduit.prototype.unsubscribeCallback = function (urlParts) {
    return true;
};

// Recevies parsed URL object and returns true or false
Conduit.prototype.subscribeCallback = function (urlParts) {
    return true;
};

// Assumes that there's a URL query parameter called 'sub' that
// maps to the subscription name in redis. Override this if you like.
Conduit.prototype.getEventName = function (urlParts) {
    return urlParts.query.sub;
};

Conduit.prototype.heartbeat = function (callbackId) {
    this.usersLastSeen[callbackId] = Date.now();
};

parsePost = function (content, callback) {
    var postObjs, entries, data;
    postObjs = [];
    try {
        data = JSON.parse(content);
        // We possibly get multiple entries per POST
        entries = Array.isArray(data.data) ? data.data : [data.data];

        for (var i in entries) {
            if (entries.hasOwnProperty(i)) {

                postObjs.push({
                    author: entries[i].from.name,
                    updated: entries[i].updated_time,
                    raw: entries[i]
                });
            }
        }
    } catch (e) {
        // Noop
        console.debug(e.description);
    }
    callback(postObjs);
};

var pushHandler = function (req, res) {
    var me, now, urlParts, content, callbackId, lastSeen, mode;

    me = this;
    now = Date.now();

    urlParts = urlParser(req.url, true);

    content = '';
    callbackId = me.getEventName(urlParts);

    // Since we are storing this in-process, in case
    // we restart the node server, people will eventually
    // get set to someting.
    if (me.usersLastSeen[callbackId] === undefined) {
        me.usersLastSeen[callbackId] = now;
    }

    lastSeen = parseInt(me.usersLastSeen[callbackId], 10);

    req.on('data', function (data) {
        content += data;
    });

    req.on('end', function () {
        mode = urlParts.query.mode;
        if (mode == 'unsubscribe') {
            if (me.unsubscribeCallback(urlParts)) {
                res.write(urlParts.query.challenge);
            }
        } else if (mode == 'subscribe') {
            if (me.subscribeCallback(urlParts)) {
                if (lastSeen + me.userLastSeenThreshold < now) {
                    res.writeHead(404);
                } else {
                    res.write(urlParts.query.challenge);
                }
            }
        } else {
            parsePost(content, function (postObjs) {
                for (var i in postObjs) {
                    if(postObjs.hasOwnProperty(i)) {
                        me.emitter.emit(callbackId, postObjs[i]);
                    }
                }
            });
        }
        res.end();
    });
};

Conduit.prototype.on = function (ev, listener) {
    return this.emitter.on(ev, listener);
};

Conduit.prototype.listen = function (port) {
    var me, callback;

    me = this;
    callback = function () {
        return pushHandler.apply(me, arguments);
    };

    http.createServer(callback).listen(port);
};
<commit_msg>Removing console.debug<commit_after>/*
Copyright (c) 2011 Nolan Caudill

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/
/*
 * Facebook-conduit
 * This is a simple script that receives events from a facebook callback and then republishes these events through and emitter.
 * I took Nolan Caudill's flickr-conduit idea and stripped the pieces specific for Flick and replaced them with Facebooks.
 *
 * @author Luiz Lopes (http://twitter.com/theprivileges)
 * @see http://search.npmjs.org/#/flickr-conduit
*/
var EventEmitter, urlParser, http, Conduit, parsePost;

EventEmitter = require('events').EventEmitter;
urlParser = require('url').parse;
http = require('http');

Conduit = function () {
    var emitter;

    // Create new emitter
    emitter = new EventEmitter();
    emitter.setMaxListeners(0);
    this.emitter = emitter;

    this.usersLastSeen = {};
    this.userLastSeenThreshold = 30 * 1000; // 5 minutes (since that's the lease length)
};

exports.Conduit = Conduit;

// Recevies parsed URL object and returns true or false
Conduit.prototype.unsubscribeCallback = function (urlParts) {
    return true;
};

// Recevies parsed URL object and returns true or false
Conduit.prototype.subscribeCallback = function (urlParts) {
    return true;
};

// Assumes that there's a URL query parameter called 'sub' that
// maps to the subscription name in redis. Override this if you like.
Conduit.prototype.getEventName = function (urlParts) {
    return urlParts.query.sub;
};

Conduit.prototype.heartbeat = function (callbackId) {
    this.usersLastSeen[callbackId] = Date.now();
};

parsePost = function (content, callback) {
    var postObjs, entries, data;
    postObjs = [];
    try {
        data = JSON.parse(content);
        // We possibly get multiple entries per POST
        entries = Array.isArray(data.data) ? data.data : [data.data];

        for (var i in entries) {
            if (entries.hasOwnProperty(i)) {

                postObjs.push({
                    author: entries[i].from.name,
                    updated: entries[i].updated_time,
                    raw: entries[i]
                });
            }
        }
    } catch (e) {
        // Noop
    }
    callback(postObjs);
};

var pushHandler = function (req, res) {
    var me, now, urlParts, content, callbackId, lastSeen, mode;

    me = this;
    now = Date.now();

    urlParts = urlParser(req.url, true);

    content = '';
    callbackId = me.getEventName(urlParts);

    // Since we are storing this in-process, in case
    // we restart the node server, people will eventually
    // get set to someting.
    if (me.usersLastSeen[callbackId] === undefined) {
        me.usersLastSeen[callbackId] = now;
    }

    lastSeen = parseInt(me.usersLastSeen[callbackId], 10);

    req.on('data', function (data) {
        content += data;
    });

    req.on('end', function () {
        mode = urlParts.query.mode;
        if (mode == 'unsubscribe') {
            if (me.unsubscribeCallback(urlParts)) {
                res.write(urlParts.query.challenge);
            }
        } else if (mode == 'subscribe') {
            if (me.subscribeCallback(urlParts)) {
                if (lastSeen + me.userLastSeenThreshold < now) {
                    res.writeHead(404);
                } else {
                    res.write(urlParts.query.challenge);
                }
            }
        } else {
            parsePost(content, function (postObjs) {
                for (var i in postObjs) {
                    if(postObjs.hasOwnProperty(i)) {
                        me.emitter.emit(callbackId, postObjs[i]);
                    }
                }
            });
        }
        res.end();
    });
};

Conduit.prototype.on = function (ev, listener) {
    return this.emitter.on(ev, listener);
};

Conduit.prototype.listen = function (port) {
    var me, callback;

    me = this;
    callback = function () {
        return pushHandler.apply(me, arguments);
    };

    http.createServer(callback).listen(port);
};
<|endoftext|>


<commit_before>"use strict";
var crc = require("../basic/crc");
var path = require("path");
var fs = require("fs");
var environment = require("./environment");
var report = require("./report");
var setting = require("./setting");
var getArgs = require('./getArgs');
var buildHtml = function (html, code) {
    var isZimoliDetected = false;
    var poweredByComment;
    var ReleaseTime = new Date().toString();
    var html = html.toString()
        .replace(/^\s*(<!doctype[^>]*?>\s*)?<!--([\s\S]*?)--!?>/i, function (_, doctype, message) {
            // `${doctype}<!--${message}\r\n${efrontReloadVersionAttribute}-->`
            poweredByComment = _;
            return "";
        })
        .replace(/<!--[\s\S]*?--!?>/g, "")
        .replace(/<title>(.*?)<\/title>/i, `<title>${process.env.TITLE || "$1"}</title>`)
        .replace(/<script\b[\s\S]*?<\/script>/ig, function (script) {
            if (/(["'`])post\1\s*,\s*(['`"])comm\/main\2/i.test(script)) {
                isZimoliDetected = true;
                return "";
            }
            if (/<script\s[^>]*?(type\s*=\s*)?(["']|)efront\-?(?:hook|main|host|script|loader)\1[^>]*?>/i.test(script)) {
                isZimoliDetected = true;
            }
            if (/\bdeleteoncompile\b/i.test(script)) {
                return "";
            }
            return script;
        });

    if (isZimoliDetected)
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script compiledinfo="${ReleaseTime} by efront ${require(path.join(__dirname, "../../package.json")).version}">\r\n<!--\r\n-function(){${code}}.call(this)\r\n-->\r\n</script>\r\n${head}`);
    if (process.env.IN_WATCH_MODE) {
        let WATCH_PORT = +process.env.WATCH_PORT;
        let reloadVersion = +new Date();
        let efrontReloadVersionAttribute = "efront-reload-version";
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script ${efrontReloadVersionAttribute}=${reloadVersion}>
        -function(){
            "use strict";
            var load = function(url, onload, method){
                var xhr = new XMLHttpRequest;
                xhr.open(method, url);
                xhr.timeout = 0;
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4 && xhr.status === 200) onload(xhr);
                };
                xhr.send("${reloadVersion}");
            };
            var reloader = function(){
                load(location.pathname + "?time=" + +new Date(), function(xhr){
                    var version = xhr.responseText.match(/\\b${efrontReloadVersionAttribute}\\s*=\\s*(\\d+)\\b/);
                    console.info("当前版本:${reloadVersion},目标版本:" + targetVersion + "正在重新加载,..");
                    if( !version || +version[1] !== ${reloadVersion}) location.reload() | console.warn("reload..", new Date);
                    else setTimeout(reloader, 200);
                }, "get");
            };
            var targetVersion = ${reloadVersion};
            var checkUpdate = function(xhr){
                targetVersion = xhr.responseText||xhr.response;
                reloader();
            };
            load("http://localhost${WATCH_PORT ? ":" + WATCH_PORT : ""}/reload/${reloadVersion}", checkUpdate, "post");
        }();
        </script>\r\n${head}`);
        global.WATCH_PROJECT_VERSION = reloadVersion;
    }
    if (poweredByComment) {
        html = html.replace(/^\s*(?:<!doctype[\s\S]*?>)?/i, poweredByComment);
    }
    return html;
};
function toApplication(responseTree) {
    var mainScript = responseTree.main ? responseTree.main : null;
    var indexHtml = responseTree["/index.html"] || responseTree["@index.html"];
    if (!indexHtml) {
        var htmlPath = path.join(__dirname, "../apps", "index.html");
        indexHtml = {
            time: 0,
            needed: true,
            fullpath: htmlPath,
            data: fs.readFileSync(htmlPath),
            realpath: htmlPath,
            version: fs.statSync(htmlPath).mtime,
            destpath: path.join("index.html"),
        };
        responseTree["/index.html"] = indexHtml;
    }
    if (mainScript) {
        Object.keys(responseTree).forEach(function (key) {
            if (/\.(jsp|php|html|asp)$/i.test(key)) {
                var response = responseTree[key];
                if (response && response.data) {
                    response.data = buildHtml(response.data, mainScript.data);
                }
            }
        });
    }
    delete responseTree["main"];
    return responseTree;
}
var toUnicode = require("../basic/toUnicode");
var rebuildData = function (responseTree) {
    var imageIndex = 0;
    Object.keys(responseTree).sort().forEach(function (k) {
        var rep = function (e) {
            if (typeof e !== "string") return String(e);

            return JSON.stringify(e.replace(/(["`']|)data(\.\w+)\:([\w\+\/\=,;\-\.]+)\1/gi, function (_, quote, ext, data) {
                var match = /^([\w\-\.\/]+;base64)?,([\w\+\/\-\=]+)$/i.exec(data);
                if (!match) return _;
                do {
                    imageIndex++;
                    var name = k + "-" + imageIndex + ext;
                } while (name in responseTree);
                var destpath = response.destpath.replace(/\.[\w]+$/, '') + '-' + imageIndex + ext;
                responseTree[name] = { destpath, data: Buffer.from(match[2], "base64"), realpath: true, url: name };
                return quote + destpath.replace(/\\/g, '/') + quote;
            }));
        };
        var response = responseTree[k];
        if (!response.data) return;
        var data = String(response.data);

        var { argNames, args, required, dependenceNamesOffset, strs, strend } = getArgs(data);
        if (strs && strs.length > 0) {
            strs = toUnicode(`[${strs.map(rep)}]`);
            data = response.data = data.slice(0, dependenceNamesOffset) + (strs.length * 2).toString(36) + strs + data.slice(strend);
        }
        if (!dependenceNamesOffset || !required) return;
        var argstr = args.concat(argNames, required.split(";").map(a => {
            return a.replace(/\.(\w+)$/g, '').replace(/\-(\w)/g, (_, a) => a.toUpperCase());
        }).join(";")).join(",");
        var arglen = (argstr.length << 1).toString(36);
        while (arglen.length < 3) {
            arglen = "0" + arglen;
        }
        response.data = arglen + argstr + data.slice(dependenceNamesOffset);
    });
};
module.exports = function (responseTree) {
    rebuildData(responseTree);
    report(responseTree);
    if (!responseTree["main"]) {
        console.warn("在您所编译的项目中没有发现主程序");
        return toApplication(responseTree);
    }
    var commbuilder = require("../efront/commbuilder");
    commbuilder.compress = false;
    var mainScript = responseTree.main;
    var mainScriptData = commbuilder(mainScript.data, "main.js", mainScript.realpath, []);
    delete commbuilder.compress;
    var versionTree = {};
    if (setting.is_file_target) {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(k) || !v.data) return;
            if (v.url !== "main") versionTree[v.url] = String(v.data);
        });
        delete versionTree["/index.html"];
        delete versionTree["@index.html"];
        for (var k in versionTree) {
            delete responseTree[k];
        }
    } else {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!v) return;
            if (/^@|^\/.*?\.[^\\\/]+$/.test(k) || !v.data) return;
            var responseVersion = crc([].map.call(v.data.toString(), e => e.charCodeAt(0))).toString(36) + (+v.data.length).toString(36);
            versionTree[v.url] = responseVersion;
        });
        delete versionTree["main"];
        delete versionTree["[]map"];
        delete versionTree["promise"];
        delete versionTree["/index.html"];
        delete versionTree["@index.html"];
    }

    return Promise.resolve(mainScriptData).then(function (mainScriptData) {
        if (setting.is_file_target) {
            var xTreeName = /(?:\bresponseTree\s*|\[\s*(["'])responseTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
            commbuilder.prepare = false;
        } else {
            var xTreeName = /(?:\bversionTree\s*|\[\s*(["'])versionTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
        }
        var code = "{\r\n" + Object.keys(versionTree).map(k => `["${k}"]:${JSON.stringify(versionTree[k]).replace(/\-\-\>/g, "-- >")}`).join(",\r\n\t") + "\r\n}";
        var versionVariableName;
        code = mainScriptData.toString()
            .replace(/(?:\.send|\[\s*(["'])send\1\s*\])\s*\((.*?)\)/g, (match, quote, data) => (versionVariableName = data || "", quote ? `[${quote}send${quote}]()` : ".send()"))
            .replace(/(['"])post\1\s*,(.*?)\s*\)/ig, `$1get$1,$2${versionVariableName && `+"${environment.EXTT}?"+` + versionVariableName})`)
            .replace(
                new RegExp(/\b/.source + xTreeName + /(\s*)=(\s*)\{.*?\}/.source),
                function (m, s1, s2) {
                    return xTreeName + `${s1}=${s2}${code}`;
                }
            );
            console.log(versionVariableName)
        return commbuilder(code, "main.js", mainScript.realpath, []);
    }).then(function (mainScriptData) {
        mainScript.data = mainScriptData;
        return toApplication(responseTree);
    });
};<commit_msg>删除log<commit_after>"use strict";
var crc = require("../basic/crc");
var path = require("path");
var fs = require("fs");
var environment = require("./environment");
var report = require("./report");
var setting = require("./setting");
var getArgs = require('./getArgs');
var buildHtml = function (html, code) {
    var isZimoliDetected = false;
    var poweredByComment;
    var ReleaseTime = new Date().toString();
    var html = html.toString()
        .replace(/^\s*(<!doctype[^>]*?>\s*)?<!--([\s\S]*?)--!?>/i, function (_, doctype, message) {
            // `${doctype}<!--${message}\r\n${efrontReloadVersionAttribute}-->`
            poweredByComment = _;
            return "";
        })
        .replace(/<!--[\s\S]*?--!?>/g, "")
        .replace(/<title>(.*?)<\/title>/i, `<title>${process.env.TITLE || "$1"}</title>`)
        .replace(/<script\b[\s\S]*?<\/script>/ig, function (script) {
            if (/(["'`])post\1\s*,\s*(['`"])comm\/main\2/i.test(script)) {
                isZimoliDetected = true;
                return "";
            }
            if (/<script\s[^>]*?(type\s*=\s*)?(["']|)efront\-?(?:hook|main|host|script|loader)\1[^>]*?>/i.test(script)) {
                isZimoliDetected = true;
            }
            if (/\bdeleteoncompile\b/i.test(script)) {
                return "";
            }
            return script;
        });

    if (isZimoliDetected)
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script compiledinfo="${ReleaseTime} by efront ${require(path.join(__dirname, "../../package.json")).version}">\r\n<!--\r\n-function(){${code}}.call(this)\r\n-->\r\n</script>\r\n${head}`);
    if (process.env.IN_WATCH_MODE) {
        let WATCH_PORT = +process.env.WATCH_PORT;
        let reloadVersion = +new Date();
        let efrontReloadVersionAttribute = "efront-reload-version";
        html = html.replace(/(<\/head>)/i, (_, head) => `\r\n<script ${efrontReloadVersionAttribute}=${reloadVersion}>
        -function(){
            "use strict";
            var load = function(url, onload, method){
                var xhr = new XMLHttpRequest;
                xhr.open(method, url);
                xhr.timeout = 0;
                xhr.onreadystatechange = function(){
                    if(xhr.readyState === 4 && xhr.status === 200) onload(xhr);
                };
                xhr.send("${reloadVersion}");
            };
            var reloader = function(){
                load(location.pathname + "?time=" + +new Date(), function(xhr){
                    var version = xhr.responseText.match(/\\b${efrontReloadVersionAttribute}\\s*=\\s*(\\d+)\\b/);
                    console.info("当前版本:${reloadVersion},目标版本:" + targetVersion + "正在重新加载,..");
                    if( !version || +version[1] !== ${reloadVersion}) location.reload() | console.warn("reload..", new Date);
                    else setTimeout(reloader, 200);
                }, "get");
            };
            var targetVersion = ${reloadVersion};
            var checkUpdate = function(xhr){
                targetVersion = xhr.responseText||xhr.response;
                reloader();
            };
            load("http://localhost${WATCH_PORT ? ":" + WATCH_PORT : ""}/reload/${reloadVersion}", checkUpdate, "post");
        }();
        </script>\r\n${head}`);
        global.WATCH_PROJECT_VERSION = reloadVersion;
    }
    if (poweredByComment) {
        html = html.replace(/^\s*(?:<!doctype[\s\S]*?>)?/i, poweredByComment);
    }
    return html;
};
function toApplication(responseTree) {
    var mainScript = responseTree.main ? responseTree.main : null;
    var indexHtml = responseTree["/index.html"] || responseTree["@index.html"];
    if (!indexHtml) {
        var htmlPath = path.join(__dirname, "../apps", "index.html");
        indexHtml = {
            time: 0,
            needed: true,
            fullpath: htmlPath,
            data: fs.readFileSync(htmlPath),
            realpath: htmlPath,
            version: fs.statSync(htmlPath).mtime,
            destpath: path.join("index.html"),
        };
        responseTree["/index.html"] = indexHtml;
    }
    if (mainScript) {
        Object.keys(responseTree).forEach(function (key) {
            if (/\.(jsp|php|html|asp)$/i.test(key)) {
                var response = responseTree[key];
                if (response && response.data) {
                    response.data = buildHtml(response.data, mainScript.data);
                }
            }
        });
    }
    delete responseTree["main"];
    return responseTree;
}
var toUnicode = require("../basic/toUnicode");
var rebuildData = function (responseTree) {
    var imageIndex = 0;
    Object.keys(responseTree).sort().forEach(function (k) {
        var rep = function (e) {
            if (typeof e !== "string") return String(e);

            return JSON.stringify(e.replace(/(["`']|)data(\.\w+)\:([\w\+\/\=,;\-\.]+)\1/gi, function (_, quote, ext, data) {
                var match = /^([\w\-\.\/]+;base64)?,([\w\+\/\-\=]+)$/i.exec(data);
                if (!match) return _;
                do {
                    imageIndex++;
                    var name = k + "-" + imageIndex + ext;
                } while (name in responseTree);
                var destpath = response.destpath.replace(/\.[\w]+$/, '') + '-' + imageIndex + ext;
                responseTree[name] = { destpath, data: Buffer.from(match[2], "base64"), realpath: true, url: name };
                return quote + destpath.replace(/\\/g, '/') + quote;
            }));
        };
        var response = responseTree[k];
        if (!response.data) return;
        var data = String(response.data);

        var { argNames, args, required, dependenceNamesOffset, strs, strend } = getArgs(data);
        if (strs && strs.length > 0) {
            strs = toUnicode(`[${strs.map(rep)}]`);
            data = response.data = data.slice(0, dependenceNamesOffset) + (strs.length * 2).toString(36) + strs + data.slice(strend);
        }
        if (!dependenceNamesOffset || !required) return;
        var argstr = args.concat(argNames, required.split(";").map(a => {
            return a.replace(/\.(\w+)$/g, '').replace(/\-(\w)/g, (_, a) => a.toUpperCase());
        }).join(";")).join(",");
        var arglen = (argstr.length << 1).toString(36);
        while (arglen.length < 3) {
            arglen = "0" + arglen;
        }
        response.data = arglen + argstr + data.slice(dependenceNamesOffset);
    });
};
module.exports = function (responseTree) {
    rebuildData(responseTree);
    report(responseTree);
    if (!responseTree["main"]) {
        console.warn("在您所编译的项目中没有发现主程序");
        return toApplication(responseTree);
    }
    var commbuilder = require("../efront/commbuilder");
    commbuilder.compress = false;
    var mainScript = responseTree.main;
    var mainScriptData = commbuilder(mainScript.data, "main.js", mainScript.realpath, []);
    delete commbuilder.compress;
    var versionTree = {};
    if (setting.is_file_target) {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (/^[@\\]|^\/.*?\.[^\\\/]+$/.test(k) || !v.data) return;
            if (v.url !== "main") versionTree[v.url] = String(v.data);
        });
        delete versionTree["/index.html"];
        delete versionTree["@index.html"];
        for (var k in versionTree) {
            delete responseTree[k];
        }
    } else {
        Object.keys(responseTree).sort().forEach(function (k) {
            var v = responseTree[k];
            if (!v) return;
            if (/^@|^\/.*?\.[^\\\/]+$/.test(k) || !v.data) return;
            var responseVersion = crc([].map.call(v.data.toString(), e => e.charCodeAt(0))).toString(36) + (+v.data.length).toString(36);
            versionTree[v.url] = responseVersion;
        });
        delete versionTree["main"];
        delete versionTree["[]map"];
        delete versionTree["promise"];
        delete versionTree["/index.html"];
        delete versionTree["@index.html"];
    }

    return Promise.resolve(mainScriptData).then(function (mainScriptData) {
        if (setting.is_file_target) {
            var xTreeName = /(?:\bresponseTree\s*|\[\s*(["'])responseTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
            commbuilder.prepare = false;
        } else {
            var xTreeName = /(?:\bversionTree\s*|\[\s*(["'])versionTree\1\s*\])\s*\:\s*(.+?)\b/m.exec(mainScriptData)[2];
        }
        var code = "{\r\n" + Object.keys(versionTree).map(k => `["${k}"]:${JSON.stringify(versionTree[k]).replace(/\-\-\>/g, "-- >")}`).join(",\r\n\t") + "\r\n}";
        var versionVariableName;
        code = mainScriptData.toString()
            .replace(/(?:\.send|\[\s*(["'])send\1\s*\])\s*\((.*?)\)/g, (match, quote, data) => (versionVariableName = data || "", quote ? `[${quote}send${quote}]()` : ".send()"))
            .replace(/(['"])post\1\s*,(.*?)\s*\)/ig, `$1get$1,$2${versionVariableName && `+"${environment.EXTT}?"+` + versionVariableName})`)
            .replace(
                new RegExp(/\b/.source + xTreeName + /(\s*)=(\s*)\{.*?\}/.source),
                function (m, s1, s2) {
                    return xTreeName + `${s1}=${s2}${code}`;
                }
            );
        return commbuilder(code, "main.js", mainScript.realpath, []);
    }).then(function (mainScriptData) {
        mainScript.data = mainScriptData;
        return toApplication(responseTree);
    });
};<|endoftext|>


<commit_before>#!/usr/bin/env node

const program = require("commander");
const version = require("../package.json").version;

program
  .version(version)
  .command("project", "Creates an AngularJS base project using TypeScript.")
  .command("component", "Creates an AngularJS component.")
  .command("controller", "Creates an AngularJS controller.")
  .command("directive", "Creates an AngularJS directive bound to a controller.")
  .command("module", "Creates an AngularJS module.")
  .command("service", "Creates an AngularJS service.")
  .parse(process.argv);<commit_msg>Comment out unavailable commands<commit_after>#!/usr/bin/env node

const program = require("commander");
const version = require("../package.json").version;

program
  .version(version)
  //.command("project", "Creates an AngularJS base project using TypeScript.")
  .command("component", "Creates an AngularJS component.")
  //.command("controller", "Creates an AngularJS controller.")
  .command("directive", "Creates an AngularJS directive bound to a controller.")
  //.command("module", "Creates an AngularJS module.")
  .command("service", "Creates an AngularJS service.")
  .parse(process.argv);<|endoftext|>


<commit_before>
var _ = require('./util.js');
var exports = module.exports;
var child_process = require('child_process');
var spawn = child_process.spawn;
var resPath = __dirname + '/node';

exports.run = function(opt) {
    process.stdout.write('starting fis-server .');
    var timeout = Math.max(opt.timeout * 1000, 5000); delete opt.timeout;
    var errMsg = 'fis-server fails to start at port [' + opt.port + '], error: ';

    if(opt.rewrite && !opt.script){
        opt.script = 'index.js';
    }

    var script = fis.util(opt.root, opt.script);

    var args = [
        resPath + '/master.js'
    ];

    var ready = false;
    var log = '';
    fis.util.map(opt, function(key, value){
        args.push('--' + key, String(value));
    });
    var server = spawn('node', args, { cwd : __dirname, detached: true});
    server.stderr.on('data', function(chunk){
        //console.log(chunk.toString('utf8'));
        if(ready) return;
        chunk = chunk.toString('utf8');
        log += chunk;
        process.stdout.write('.');
        if(chunk.indexOf('master is running') >= 0){
            ready = true;
            process.stdout.write(' at port [' + opt.port + ']\n');

            //copy fis ico
            var favicon = fis.util(opt.root, 'favicon.ico');
            if(!fis.util.exists(favicon)){
                fis.util.copy(resPath + '/vendor/favicon.ico', favicon);
            }

            //copy script
            if(opt.rewrite){
                if(!fis.util.exists(script)){
                    console.log(resPath + '/vendor/' + opt.script);
                    fis.util.copy(resPath + '/vendor/' + opt.script, script);
                }
            }
            setTimeout(function(){
                _.open('http://127.0.0.1' + (opt.port == 80 ? '/' : ':' + opt.port + '/'), function(){
                    process.exit();
                });
            }, 200);
        }
        else if(chunk.indexOf('Exception') > 0) {
            process.stdout.write(' fail\n');
            try { process.kill(server.pid, 'SIGINT'); } catch(e){}
            var match = chunk.match(/exception:?\s+([^\r\n]+)/i);
            if(match){
                errMsg += match[1];
            } else {
                errMsg += 'unknown';
            }
            console.log(log);
            fis.log.error(errMsg);
        }
    });
    server.on('error', function(err){
        try {
            process.kill(server.pid, 'SIGINT');
        } catch(e){}
        fis.log.error(err);
    });
    server.unref();
    fis.util.write(_.getPidFile(), server.pid);
    setTimeout(function(){
        process.stdout.write(' fail\n');
        if(log) console.log(log);
        fis.log.error(errMsg + 'timeout');
    }, timeout);
};<commit_msg>delete debug info<commit_after>
var _ = require('./util.js');
var exports = module.exports;
var child_process = require('child_process');
var spawn = child_process.spawn;
var resPath = __dirname + '/node';

exports.run = function(opt) {
    process.stdout.write('starting fis-server .');
    var timeout = Math.max(opt.timeout * 1000, 5000); delete opt.timeout;
    var errMsg = 'fis-server fails to start at port [' + opt.port + '], error: ';

    if(opt.rewrite && !opt.script){
        opt.script = 'index.js';
    }

    var script = fis.util(opt.root, opt.script);

    var args = [
        resPath + '/master.js'
    ];

    var ready = false;
    var log = '';
    fis.util.map(opt, function(key, value){
        args.push('--' + key, String(value));
    });
    var server = spawn('node', args, { cwd : __dirname, detached: true});
    server.stderr.on('data', function(chunk){
        //console.log(chunk.toString('utf8'));
        if(ready) return;
        chunk = chunk.toString('utf8');
        log += chunk;
        process.stdout.write('.');
        if(chunk.indexOf('master is running') >= 0){
            ready = true;
            process.stdout.write(' at port [' + opt.port + ']\n');

            //copy fis ico
            var favicon = fis.util(opt.root, 'favicon.ico');
            if(!fis.util.exists(favicon)){
                fis.util.copy(resPath + '/vendor/favicon.ico', favicon);
            }

            //copy script
            if(opt.rewrite){
                if(!fis.util.exists(script)){
                    fis.util.copy(resPath + '/vendor/' + opt.script, script);
                }
            }
            setTimeout(function(){
                _.open('http://127.0.0.1' + (opt.port == 80 ? '/' : ':' + opt.port + '/'), function(){
                    process.exit();
                });
            }, 200);
        }
        else if(chunk.indexOf('Exception') > 0) {
            process.stdout.write(' fail\n');
            try { process.kill(server.pid, 'SIGINT'); } catch(e){}
            var match = chunk.match(/exception:?\s+([^\r\n]+)/i);
            if(match){
                errMsg += match[1];
            } else {
                errMsg += 'unknown';
            }
            console.log(log);
            fis.log.error(errMsg);
        }
    });
    server.on('error', function(err){
        try {
            process.kill(server.pid, 'SIGINT');
        } catch(e){}
        fis.log.error(err);
    });
    server.unref();
    fis.util.write(_.getPidFile(), server.pid);
    setTimeout(function(){
        process.stdout.write(' fail\n');
        if(log) console.log(log);
        fis.log.error(errMsg + 'timeout');
    }, timeout);
};<|endoftext|>


<commit_before>var fs = require('fs'),
    request = require('request'),
	async = require("async");

var baseURI =  'http://www.facets.la/wallpaper/W_';
var year = 2013;
var id = 1;
var savePath = process.argv[2];

var download = function(uri, savePath, callback){
	if(id == 330)
		year = "2014";
  request.head(uri, function(err, res, body){
	console.log('Downloading '+id);
    //console.log('content-type:', res.headers['content-type']);
    console.log('content-length:', res.headers['content-length']);
	if(typeof res.headers['content-length'] !== "undefined"){
    request(uri).pipe(fs.createWriteStream(savePath)).on('close', callback);
	if(id++ <= 365){
		download(baseURI+year+'_'+id+'.jpg', savePath+id+'.jpg', function(){
		//console.log('done');
		});}
	}
	else{
		if(id++ <= 365){
		download(baseURI+year+'_'+id+'.jpg', savePath+id+'.jpg', function(){
		//console.log('done');
		});}
		}
  });
};

download(baseURI+year+'_'+id+'.jpg', savePath+id+'.jpg', function(){
  console.log('done');
});
<commit_msg>Coded from scrap<commit_after>//Required modules
var fs = require('fs'),
		 cheerio = require('cheerio'),
		 request = require('request');

//Default Variables
var baseURI =  'http://www.facets.la/';
var year = 2013;
var id = 1;
var savePath = process.argv[2];

//Download Function
var download = function(uri, filename, callback){
	request({ uri: uri }, function(err, res, body){
		var $ = cheerio.load(body);
		var imgDiv = $('#facet-wallpaper').children()['0'];
		if(err)
			console.log("Error");
		if(typeof imgDiv !== 'undefined') {
		request(imgDiv.attribs.src).pipe(fs.createWriteStream(filename)).on('close', callback);}
		else{
			id++;
			request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);
		}
	});
};

//Main Function
console.log("Downloading . . .");

// Loop function to create a recursive effect
(function loop(){
	download(baseURI+year+'/'+id+'/wallpaper/', savePath+id+'.jpg',
	function(){
		console.log(((id/365)*100).toFixed(2)+'% completed');
		if(id == 330)
			year = "2014";
		if(id <= 365){
			id=id+1;
			loop();
		}
		});
})(1)
<|endoftext|>