<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 FB_TEXT_LIMIT = 640;
var barbrad = 'true';

class FacebookBot {
    constructor() {
        this.apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
        this.sessionIds = new Map();
        this.messagesDelay = 200;
    }

    doDataResponse(sender, facebookResponseData) {
        if (!Array.isArray(facebookResponseData)) {
            console.log('Response as formatted message');
            this.sendFBMessage(sender, facebookResponseData)
                .catch(err => console.error(err));
        } else {
            async.eachSeries(facebookResponseData, (facebookMessage, callback) => {
                if (facebookMessage.sender_action) {
                    console.log('Response as sender action');
                    this.sendFBSenderAction(sender, facebookMessage.sender_action)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
                else {
                    console.log('Response as formatted message');
                    this.sendFBMessage(sender, facebookMessage)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
            }, (err) => {
                if (err) {
                    console.error(err);
                } else {
                    console.log('Data response completed');
                }
            });
        }
    }

    doRichContentResponse(sender, messages) {
        let facebookMessages = []; // array with result messages

        for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
            let message = messages[messageIndex];

            switch (message.type) {
                //message.type 0 means text message
                case 0:
                    // speech: ["hi"]
                    // we have to get value from fulfillment.speech, because of here is raw speech
                    if (message.speech) {

                        let splittedText = this.splitResponse(message.speech);

                        splittedText.forEach(s => {
                            facebookMessages.push({text: s});
                        });
                    }

                    break;
                //message.type 1 means card message
                case 1: {
                    let carousel = [message];

                    for (messageIndex++; messageIndex < messages.length; messageIndex++) {
                        if (messages[messageIndex].type == 1) {
                            carousel.push(messages[messageIndex]);
                        } else {
                            messageIndex--;
                            break;
                        }
                    }

                    let facebookMessage = {};
                    carousel.forEach((c) => {
                        // buttons: [ {text: "hi", postback: "postback"} ], imageUrl: "", title: "", subtitle: ""

                        let card = {};

                        card.title = c.title;
                        card.image_url = c.imageUrl;
                        if (this.isDefined(c.subtitle)) {
                            card.subtitle = c.subtitle;
                        }
                        //If button is involved in.
                        if (c.buttons.length > 0) {
                            let buttons = [];
                            for (let buttonIndex = 0; buttonIndex < c.buttons.length; buttonIndex++) {
                                let button = c.buttons[buttonIndex];

                                if (button.text) {
                                    let postback = button.postback;
                                    if (!postback) {
                                        postback = button.text;
                                    }

                                    let buttonDescription = {
                                        title: button.text
                                    };

                                    if (postback.startsWith("http")) {
                                        buttonDescription.type = "web_url";
                                        buttonDescription.url = postback;
                                    } else {
                                        buttonDescription.type = "postback";
                                        buttonDescription.payload = postback;
                                    }

                                    buttons.push(buttonDescription);
                                }
                            }

                            if (buttons.length > 0) {
                                card.buttons = buttons;
                            }
                        }

                        if (!facebookMessage.attachment) {
                            facebookMessage.attachment = {type: "template"};
                        }

                        if (!facebookMessage.attachment.payload) {
                            facebookMessage.attachment.payload = {template_type: "generic", elements: []};
                        }

                        facebookMessage.attachment.payload.elements.push(card);
                    });

                    facebookMessages.push(facebookMessage);
                }

                    break;
                //message.type 2 means quick replies message
                case 2: {
                    if (message.replies && message.replies.length > 0) {
                        let facebookMessage = {};

                        facebookMessage.text = message.title ? message.title : 'Choose an item';
                        facebookMessage.quick_replies = [];

                        message.replies.forEach((r) => {
                            facebookMessage.quick_replies.push({
                                content_type: "text",
                                title: r,
                                payload: r
                            });
                        });

                        facebookMessages.push(facebookMessage);
                    }
                }

                    break;
                //message.type 3 means image message
                case 3:

                    if (message.imageUrl) {
                        let facebookMessage = {};

                        // "imageUrl": "http://example.com/image.jpg"
                        facebookMessage.attachment = {type: "image"};
                        facebookMessage.attachment.payload = {url: message.imageUrl};

                        facebookMessages.push(facebookMessage);
                    }

                    break;
                //message.type 4 means custom payload message
                case 4:
                    if (message.payload && message.payload.facebook) {
                        facebookMessages.push(message.payload.facebook);
                    }
                    break;

                default:
                    break;
            }
        }

        return new Promise((resolve, reject) => {
            async.eachSeries(facebookMessages, (msg, callback) => {
                    this.sendFBSenderAction(sender, "typing_on")
                        .then(() => this.sleep(this.messagesDelay))
                        .then(() => this.sendFBMessage(sender, msg))
                        .then(() => callback())
                        .catch(callback);
                },
                (err) => {
                    if (err) {
                        console.error(err);
                        reject(err);
                    } else {
                        console.log('Messages sent');
                        resolve();
                    }
                });
        });

    }

    doTextResponse(sender, responseText) {
        console.log('Response as text message');
        // facebook API limit for text length is 640,
        // so we must split message if needed
        let splittedText = this.splitResponse(responseText);

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

     //which webhook event
    getEventText(event) {
        if (event.message) {
            if (event.message.quick_reply && event.message.quick_reply.payload) {
                return event.message.quick_reply.payload;
            }

            if (event.message.text) {
                return event.message.text;
            }
        }

        if (event.postback && event.postback.payload) {
            console.log('Postback Webhook')
            //console.log(event.postback.payload);
            console.log(event.postback.referral.ref);
            return event.postback.payload;
        }

        return null;

    }

    processEvent(event) {
        const sender = event.sender.id.toString();
        const text = this.getEventText(event);

        if (text) {

            // Handle a text message from the sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            console.log("Text", text);
            //send user's text to api.ai service
            let apiaiRequest = this.apiAiService.textRequest(text,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });

            //get response from api.ai
            apiaiRequest.on('response', (response) => {
                if (this.isDefined(response.result) && this.isDefined(response.result.fulfillment)) {
                    let responseText = response.result.fulfillment.speech;
                    let responseData = response.result.fulfillment.data;
                    let responseMessages = response.result.fulfillment.messages;

                    let action = response.result.action;

                    if (this.isDefined(responseData) && this.isDefined(responseData.facebook)) {
                        let facebookResponseData = responseData.facebook;
                        this.doDataResponse(sender, facebookResponseData);
                    } else if (this.isDefined(responseMessages) && responseMessages.length > 0) {
                        this.doRichContentResponse(sender, responseMessages);
                    }
                    else if (this.isDefined(responseText)) {
                        this.doTextResponse(sender, responseText);
                    }

                }
            });

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

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

        return this.chunkString(str, FB_TEXT_LIMIT);
    }

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

        let output = [];

        while (s[curr]) {
            if (s[curr++] == ' ') {
                output.push(s.substring(prev, curr));
                prev = curr;
                curr += len;
            }
            else {
                let 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;
    }

    sendFBMessage(sender, messageData) {
        return new Promise((resolve, reject) => {
            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) => {
                if (error) {
                    console.log('Error sending message: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.log('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    sendFBSenderAction(sender, action) {
        return new Promise((resolve, reject) => {
            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) => {
                if (error) {
                    console.error('Error sending action: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.error('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    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);
                }
            });
    }

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

        if (!obj) {
            return false;
        }

        return obj != null;
    }

    sleep(delay) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), delay);
        });
    }

}

let facebookBot = new FacebookBot();

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(() => {
            facebookBot.doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        const 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.is_echo ||
                            event.postback && event.postback.payload) {
                            facebookBot.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);
});

facebookBot.doSubscribeRequest();
<commit_msg>Update app.js<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 FB_TEXT_LIMIT = 640;
var barbrad = 'true';

class FacebookBot {
    constructor() {
        this.apiAiService = apiai(APIAI_ACCESS_TOKEN, {language: APIAI_LANG, requestSource: "fb"});
        this.sessionIds = new Map();
        this.messagesDelay = 200;
    }

    doDataResponse(sender, facebookResponseData) {
        if (!Array.isArray(facebookResponseData)) {
            console.log('Response as formatted message');
            this.sendFBMessage(sender, facebookResponseData)
                .catch(err => console.error(err));
        } else {
            async.eachSeries(facebookResponseData, (facebookMessage, callback) => {
                if (facebookMessage.sender_action) {
                    console.log('Response as sender action');
                    this.sendFBSenderAction(sender, facebookMessage.sender_action)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
                else {
                    console.log('Response as formatted message');
                    this.sendFBMessage(sender, facebookMessage)
                        .then(() => callback())
                        .catch(err => callback(err));
                }
            }, (err) => {
                if (err) {
                    console.error(err);
                } else {
                    console.log('Data response completed');
                }
            });
        }
    }

    doRichContentResponse(sender, messages) {
        let facebookMessages = []; // array with result messages

        for (let messageIndex = 0; messageIndex < messages.length; messageIndex++) {
            let message = messages[messageIndex];

            switch (message.type) {
                //message.type 0 means text message
                case 0:
                    // speech: ["hi"]
                    // we have to get value from fulfillment.speech, because of here is raw speech
                    if (message.speech) {

                        let splittedText = this.splitResponse(message.speech);

                        splittedText.forEach(s => {
                            facebookMessages.push({text: s});
                        });
                    }

                    break;
                //message.type 1 means card message
                case 1: {
                    let carousel = [message];

                    for (messageIndex++; messageIndex < messages.length; messageIndex++) {
                        if (messages[messageIndex].type == 1) {
                            carousel.push(messages[messageIndex]);
                        } else {
                            messageIndex--;
                            break;
                        }
                    }

                    let facebookMessage = {};
                    carousel.forEach((c) => {
                        // buttons: [ {text: "hi", postback: "postback"} ], imageUrl: "", title: "", subtitle: ""

                        let card = {};

                        card.title = c.title;
                        card.image_url = c.imageUrl;
                        if (this.isDefined(c.subtitle)) {
                            card.subtitle = c.subtitle;
                        }
                        //If button is involved in.
                        if (c.buttons.length > 0) {
                            let buttons = [];
                            for (let buttonIndex = 0; buttonIndex < c.buttons.length; buttonIndex++) {
                                let button = c.buttons[buttonIndex];

                                if (button.text) {
                                    let postback = button.postback;
                                    if (!postback) {
                                        postback = button.text;
                                    }

                                    let buttonDescription = {
                                        title: button.text
                                    };

                                    if (postback.startsWith("http")) {
                                        buttonDescription.type = "web_url";
                                        buttonDescription.url = postback;
                                    } else {
                                        buttonDescription.type = "postback";
                                        buttonDescription.payload = postback;
                                    }

                                    buttons.push(buttonDescription);
                                }
                            }

                            if (buttons.length > 0) {
                                card.buttons = buttons;
                            }
                        }

                        if (!facebookMessage.attachment) {
                            facebookMessage.attachment = {type: "template"};
                        }

                        if (!facebookMessage.attachment.payload) {
                            facebookMessage.attachment.payload = {template_type: "generic", elements: []};
                        }

                        facebookMessage.attachment.payload.elements.push(card);
                    });

                    facebookMessages.push(facebookMessage);
                }

                    break;
                //message.type 2 means quick replies message
                case 2: {
                    if (message.replies && message.replies.length > 0) {
                        let facebookMessage = {};

                        facebookMessage.text = message.title ? message.title : 'Choose an item';
                        facebookMessage.quick_replies = [];

                        message.replies.forEach((r) => {
                            facebookMessage.quick_replies.push({
                                content_type: "text",
                                title: r,
                                payload: r
                            });
                        });

                        facebookMessages.push(facebookMessage);
                    }
                }

                    break;
                //message.type 3 means image message
                case 3:

                    if (message.imageUrl) {
                        let facebookMessage = {};

                        // "imageUrl": "http://example.com/image.jpg"
                        facebookMessage.attachment = {type: "image"};
                        facebookMessage.attachment.payload = {url: message.imageUrl};

                        facebookMessages.push(facebookMessage);
                    }

                    break;
                //message.type 4 means custom payload message
                case 4:
                    if (message.payload && message.payload.facebook) {
                        facebookMessages.push(message.payload.facebook);
                    }
                    break;

                default:
                    break;
            }
        }

        return new Promise((resolve, reject) => {
            async.eachSeries(facebookMessages, (msg, callback) => {
                    this.sendFBSenderAction(sender, "typing_on")
                        .then(() => this.sleep(this.messagesDelay))
                        .then(() => this.sendFBMessage(sender, msg))
                        .then(() => callback())
                        .catch(callback);
                },
                (err) => {
                    if (err) {
                        console.error(err);
                        reject(err);
                    } else {
                        console.log('Messages sent');
                        resolve();
                    }
                });
        });

    }

    doTextResponse(sender, responseText) {
        console.log('Response as text message');
        // facebook API limit for text length is 640,
        // so we must split message if needed
        let splittedText = this.splitResponse(responseText);

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

     //which webhook event
    getEventText(event) {
        if (event.message) {
            if (event.message.quick_reply && event.message.quick_reply.payload) {
                return event.message.quick_reply.payload;
            }

            if (event.message.text) {
                return event.message.text;
            }
        }

        if (event.postback && event.postback.payload) {
            console.log('Postback Webhook')
            console.log(event.postback.payload);
            //console.log(event.postback.referral.ref);
            return event.postback.payload;
        }

        return null;

    }

    processEvent(event) {
        const sender = event.sender.id.toString();
        const text = this.getEventText(event);

        if (text) {

            // Handle a text message from the sender
            if (!this.sessionIds.has(sender)) {
                this.sessionIds.set(sender, uuid.v4());
            }

            console.log("Text", text);
            //send user's text to api.ai service
            let apiaiRequest = this.apiAiService.textRequest(text,
                {
                    sessionId: this.sessionIds.get(sender),
                    originalRequest: {
                        data: event,
                        source: "facebook"
                    }
                });

            //get response from api.ai
            apiaiRequest.on('response', (response) => {
                if (this.isDefined(response.result) && this.isDefined(response.result.fulfillment)) {
                    let responseText = response.result.fulfillment.speech;
                    let responseData = response.result.fulfillment.data;
                    let responseMessages = response.result.fulfillment.messages;

                    let action = response.result.action;

                    if (this.isDefined(responseData) && this.isDefined(responseData.facebook)) {
                        let facebookResponseData = responseData.facebook;
                        this.doDataResponse(sender, facebookResponseData);
                    } else if (this.isDefined(responseMessages) && responseMessages.length > 0) {
                        this.doRichContentResponse(sender, responseMessages);
                    }
                    else if (this.isDefined(responseText)) {
                        this.doTextResponse(sender, responseText);
                    }

                }
            });

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

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

        return this.chunkString(str, FB_TEXT_LIMIT);
    }

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

        let output = [];

        while (s[curr]) {
            if (s[curr++] == ' ') {
                output.push(s.substring(prev, curr));
                prev = curr;
                curr += len;
            }
            else {
                let 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;
    }

    sendFBMessage(sender, messageData) {
        return new Promise((resolve, reject) => {
            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) => {
                if (error) {
                    console.log('Error sending message: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.log('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    sendFBSenderAction(sender, action) {
        return new Promise((resolve, reject) => {
            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) => {
                if (error) {
                    console.error('Error sending action: ', error);
                    reject(error);
                } else if (response.body.error) {
                    console.error('Error: ', response.body.error);
                    reject(new Error(response.body.error));
                }

                resolve();
            });
        });
    }

    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);
                }
            });
    }

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

        if (!obj) {
            return false;
        }

        return obj != null;
    }

    sleep(delay) {
        return new Promise((resolve, reject) => {
            setTimeout(() => resolve(), delay);
        });
    }

}

let facebookBot = new FacebookBot();

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(() => {
            facebookBot.doSubscribeRequest();
        }, 3000);
    } else {
        res.send('Error, wrong validation token');
    }
});

app.post('/webhook/', (req, res) => {
    try {
        const 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.is_echo ||
                            event.postback && event.postback.payload) {
                            facebookBot.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);
});

facebookBot.doSubscribeRequest();
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2012, Ryuichi Okumura. All rights reserved.
 * Code licensed under the BSD License:
 * https://github.com/okuryu/node-iyql/blob/master/LICENSE.md
 */
'use strict';

var fs = require('fs'),
  path = require('path'),
  repl = require('repl'),
  querystring = require('querystring'),
  url = require('url'),
  nopt = require('nopt'),
  request = require('request'),
  knownOptions = {
    endpoint: url,
    env: url,
    help: Boolean,
    ssl: Boolean,
    version: Boolean
  },
  shortHands = {
    p: ['--endpoint'],
    e: ['--env'],
    h: ['--help'],
    s: ['--ssl'],
    v: ['--version']
  },
  options = nopt(knownOptions, shortHands);

function showHelp() {
  var help = 'Usage: iyql [options]\n' +
    '\n' +
    'Options:\n' +
    '  -p, --endpoint set YQL endpoint URL. default: ' +
    'http://query.yahooapis.com/v1/public/yql\n' +
    '  -e, --env      set YQL env URL\n' +
    '  -h, --help     print help\n' +
    '  -s, --ssl      use HTTPS endpoint\n' +
    '  -v, --version  print version\n';

  process.stdout.write(help);
}

function showVersion() {
  var version = require('../package.json').version;

  process.stdout.write('v' + version + '\n');
}

function replCallback(cmd, context, filename, callback) {
  var endpoint,
    query = cmd.trim(),
    qs = querystring.stringify({
      diagnostics: 'true',
      debug: 'true',
      env: options.env || 'http://www.datatables.org/alltables.env',
      format: 'json',
      q: query
    });

  if (options.endpoint) {
    endpoint = options.endpoint;
  } else {
    endpoint = options.ssl ? 'https' : 'http';
    endpoint += '://query.yahooapis.com/v1/public/yql';
  }

  request(endpoint + '?' + qs, function (error, response, body) {
    callback(JSON.stringify(JSON.parse(body), null, 2));
  });
}

function main() {
  if (options.help) {
    showHelp();
    process.exit();
  } else if (options.version) {
    showVersion();
    process.exit();
  }

  repl.start({
    prompt: 'iyql> ',
    eval: replCallback,
    ignoreUndefined: true
  });
}

exports.route = function () {
  main();
};
<commit_msg>No more one var<commit_after>/**
 * Copyright (c) 2012, Ryuichi Okumura. All rights reserved.
 * Code licensed under the BSD License:
 * https://github.com/okuryu/node-iyql/blob/master/LICENSE.md
 */
'use strict';

var fs = require('fs');
var path = require('path');
var repl = require('repl');
var querystring = require('querystring');
var url = require('url');
var nopt = require('nopt');
var request = require('request');
var knownOptions = {
  endpoint: url,
  env: url,
  help: Boolean,
  ssl: Boolean,
  version: Boolean
};
var shortHands = {
  p: ['--endpoint'],
  e: ['--env'],
  h: ['--help'],
  s: ['--ssl'],
  v: ['--version']
};
var options = nopt(knownOptions, shortHands);

function showHelp() {
  var help = 'Usage: iyql [options]\n' +
    '\n' +
    'Options:\n' +
    '  -p, --endpoint set YQL endpoint URL. default: ' +
    'http://query.yahooapis.com/v1/public/yql\n' +
    '  -e, --env      set YQL env URL\n' +
    '  -h, --help     print help\n' +
    '  -s, --ssl      use HTTPS endpoint\n' +
    '  -v, --version  print version\n';

  process.stdout.write(help);
}

function showVersion() {
  var version = require('../package.json').version;

  process.stdout.write('v' + version + '\n');
}

function replCallback(cmd, context, filename, callback) {
  var endpoint;
  var query = cmd.trim();
  var qs = querystring.stringify({
    diagnostics: 'true',
    debug: 'true',
    env: options.env || 'http://www.datatables.org/alltables.env',
    format: 'json',
    q: query
  });

  if (options.endpoint) {
    endpoint = options.endpoint;
  } else {
    endpoint = options.ssl ? 'https' : 'http';
    endpoint += '://query.yahooapis.com/v1/public/yql';
  }

  request(endpoint + '?' + qs, function (error, response, body) {
    callback(JSON.stringify(JSON.parse(body), null, 2));
  });
}

function main() {
  if (options.help) {
    showHelp();
    process.exit();
  } else if (options.version) {
    showVersion();
    process.exit();
  }

  repl.start({
    prompt: 'iyql> ',
    eval: replCallback,
    ignoreUndefined: true
  });
}

exports.route = function () {
  main();
};
<|endoftext|>


<commit_before>

const _                 = require('lodash');
const bodyParser        = require('body-parser');
const compression       = require('compression');
const cookieParser      = require('cookie-parser');
const cookieSession     = require('cookie-session');
const express           = require('express');
const i18nFsBackend     = require('i18next-node-fs-backend');
const i18nMiddleware    = require('i18next-express-middleware');
const i18next           = require('i18next');

const cache             = require('./cache');
const cls               = require('./cls');
const config            = require('./config');
const db                = require('./db/db');
const errorHandler      = require('./connect/errorhandler');
const flash             = require('./connect/flash');
const locals            = require('./connect/locals');
const multipart         = require('./connect/multipart');
const validator         = require('./connect/validator');
const logger            = require('./logger');
const mailer            = require('./mailer');
const plugins           = require('./plugins');

//
const app = module.exports = express();

const ENGINES = {
  'dust':       require('./engines/dust'),
  'igo-dust':   require('./engines/igo-dust')
};

const SERVICES = [ config, logger, cache, db, mailer, cls, plugins ]

//
module.exports.configure = function() {

  SERVICES.forEach(service => service.init());

  i18next
    .use(i18nMiddleware.LanguageDetector)
    .use(i18nFsBackend)
    .init(config.i18n);

  app.enable('trust proxy');

  // template engine
  const engine = ENGINES[config.engine] || ENGINES.dust;
  engine.init(app);
  app.engine = engine;

  app.use(compression());
  app.use(express.static('public'));

  if (config.env !== 'test') {
    app.use(errorHandler.init(app));
    app.use(cookieParser(config.signedCookiesSecret));
    app.use(cookieSession(config.cookieSessionConfig));
    app.use(bodyParser.json({ limit: config.bodyParser.limit }));
    app.use(bodyParser.urlencoded({ limit: config.bodyParser.limit, extended: true }));
    app.use(multipart);
  }

  app.use(flash);
  app.use(validator);
  app.use(i18nMiddleware.handle(i18next));
  app.use(locals);
  app.use(engine.middleware);

  // load routes
  const routes = require('./routes');
  routes.init(app);

  if (config.env !== 'test') {
    app.use(errorHandler.error);
  }

}

// configured: callback function invoked when app is configured
// started: callback function invoked when server is started
module.exports.run = function(configured, started) {

  module.exports.configure();
  configured && configured();

  app.server = app.listen(config.httpport, function() {
    logger.info('Listening to port %s', config.httpport);
    started && started();
  });
};
<commit_msg>Igo Dust is default template engine<commit_after>

const _                 = require('lodash');
const bodyParser        = require('body-parser');
const compression       = require('compression');
const cookieParser      = require('cookie-parser');
const cookieSession     = require('cookie-session');
const express           = require('express');
const i18nFsBackend     = require('i18next-node-fs-backend');
const i18nMiddleware    = require('i18next-express-middleware');
const i18next           = require('i18next');

const cache             = require('./cache');
const cls               = require('./cls');
const config            = require('./config');
const db                = require('./db/db');
const errorHandler      = require('./connect/errorhandler');
const flash             = require('./connect/flash');
const locals            = require('./connect/locals');
const multipart         = require('./connect/multipart');
const validator         = require('./connect/validator');
const logger            = require('./logger');
const mailer            = require('./mailer');
const plugins           = require('./plugins');

//
const app = module.exports = express();

const ENGINES = {
  'dust':       require('./engines/dust'),
  'igo-dust':   require('./engines/igo-dust')
};

const SERVICES = [ config, logger, cache, db, mailer, cls, plugins ]

//
module.exports.configure = function() {

  SERVICES.forEach(service => service.init());

  i18next
    .use(i18nMiddleware.LanguageDetector)
    .use(i18nFsBackend)
    .init(config.i18n);

  app.enable('trust proxy');

  // template engine
  const engine = ENGINES[config.engine] || ENGINES['igo-dust'];
  engine.init(app);
  app.engine = engine;

  app.use(compression());
  app.use(express.static('public'));

  if (config.env !== 'test') {
    app.use(errorHandler.init(app));
    app.use(cookieParser(config.signedCookiesSecret));
    app.use(cookieSession(config.cookieSessionConfig));
    app.use(bodyParser.json({ limit: config.bodyParser.limit }));
    app.use(bodyParser.urlencoded({ limit: config.bodyParser.limit, extended: true }));
    app.use(multipart);
  }

  app.use(flash);
  app.use(validator);
  app.use(i18nMiddleware.handle(i18next));
  app.use(locals);
  app.use(engine.middleware);

  // load routes
  const routes = require('./routes');
  routes.init(app);

  if (config.env !== 'test') {
    app.use(errorHandler.error);
  }

}

// configured: callback function invoked when app is configured
// started: callback function invoked when server is started
module.exports.run = function(configured, started) {

  module.exports.configure();
  configured && configured();

  app.server = app.listen(config.httpport, function() {
    logger.info('Listening to port %s', config.httpport);
    started && started();
  });
};
<|endoftext|>


<commit_before>const write_options = { spaces : '\t' };

const defaults = require('defaults-deep');
const jsonfile = require('jsonfile');

const file_config = app_path + '/config.json';
const file_status = app_path + '/status.json';

const config_default = require('config-default');
const status_default = require('status-default');

const status_bluetooth_default = require('status-bluetooth-default');
const status_lights_default    = require('status-lights-default');
const status_mid_default       = require('status-mid-default');
const status_power_default     = require('status-power-default');

// Read config+status
async function read(read_cb = null) {
	// read JSON config file
	await json.config_read();

	// read JSON status file
	await json.status_read();

	// Execute callback
	typeof read_cb === 'function' && await read_cb();
	read_cb = null;
}

// Write config+status
async function write(write_cb = null) {
	// Write JSON config file
	await json.config_write();

	// Write JSON status file
	await json.status_write();

	// Execute callback
	typeof write_cb === 'function' && await write_cb();
	write_cb = null;
}

// Reset both modules and status vars
function reset(reset_cb = null) {
	json.modules_reset(() => { // Set modules as not ready
		json.status_reset(() => { // Reset some variables
			switch (config.json.write_on_reset) {
				case false : {
					typeof reset_cb === 'function' && process.nextTick(reset_cb);
					reset_cb = undefined;

					break;
				}

				default : {
					json.write(() => { // Write JSON files
						typeof reset_cb === 'function' && process.nextTick(reset_cb);
						reset_cb = undefined;
					});
				}
			}
		});
	});
}

// Read config JSON
async function config_read(config_read_cb = null) {
	let config_data;

	try {
		config_data = await jsonfile.readFileSync(file_config);
	}
	catch (err) {
		log.msg('Failed reading config, applying default config');

		config = config_default;
		await json.config_write(config_read_cb);
		return false;
	}

	// Lay the default values on top of the read object, in case new values were added
	config = await defaults(config_data, config_default);

	log.msg('Read config');

	typeof config_read_cb === 'function' && await config_read_cb();
	config_read_cb = undefined;
}

// Read status JSON
async function status_read(status_read_cb = null) {
	let status_data;

	try {
		status_data = await jsonfile.readFileSync(file_status);
	}
	catch (err) {
		log.msg('Failed reading status, applying default status');

		status = status_default;
		await json.status_write(status_read_cb);
		return false;
	}

	// Lay the default values on top of the read object, in case new values were added
	status = await defaults(status_data, status_default);

	log.msg('Read status');

	typeof status_read_cb === 'function' && await status_read_cb();
	status_read_cb = undefined;
}

// Write config JSON
async function config_write(config_write_cb = null) {
	// Don't write if empty
	if (typeof config.system === 'undefined') {
		log.msg('Failed writing config, config object empty');

		if (typeof config_write_cb !== 'function') return;
		await config_write_cb();
		config_write_cb = undefined;

		return;
	}

	try {
		await jsonfile.writeFileSync(file_config, config, write_options);
	}
	catch (err) {
		log.msg('Failed writing config');

		if (typeof config_write_cb !== 'function') return;
		await config_write_cb();
		config_write_cb = undefined;

		return false;
	}

	await log.msg('Wrote config');

	if (typeof config_write_cb !== 'function') return;
	await config_write_cb();
	config_write_cb = undefined;
}

// Write status JSON
async function status_write(status_write_cb = null) {
	// Don't write if empty
	if (typeof status.system === 'undefined') {
		log.msg('Failed writing status, status object empty');

		if (typeof status_write_cb !== 'function') return;
		await status_write_cb();
		status_write_cb = undefined;

		return;
	}

	try {
		await jsonfile.writeFileSync(file_status, status, write_options);
	}
	catch (err) {
		log.msg('Failed writing status');

		if (typeof status_write_cb !== 'function') return;
		await status_write_cb();
		status_write_cb = undefined;

		return false;
	}

	await log.msg('Wrote status');

	if (typeof status_write_cb !== 'function') return;
	await status_write_cb();
	status_write_cb = undefined;
}

// Set modules as not ready
function modules_reset(modules_reset_cb = null) {
	for (let module in bus.modules.modules) {
		module = module.toLowerCase();

		// Skip modules without entry in status object
		if (typeof status[module] === 'undefined') continue;
		if (status[module]        === null)        continue;

		switch (module) {
			case 'dia' : break;
			case 'glo' : break;
			case 'loc' : break;

			default : {
				status[module].reset = true;
				status[module].ready = false;
			}
		}
	}

	status.rad.source_name = 'off';

	log.msg('Reset modules');

	typeof modules_reset_cb === 'function' && process.nextTick(modules_reset_cb);
	modules_reset_cb = undefined;
}

// Reset basic variables
function status_reset_basic(status_reset_basic_cb = null) {
	status.engine.running = false;

	status.vehicle.handbrake      = false;
	status.vehicle.ignition       = 'off';
	status.vehicle.ignition_level = 0;
	status.vehicle.reverse        = false;

	log.msg('Reset basic status');

	typeof status_reset_basic_cb === 'function' && process.nextTick(status_reset_basic_cb);
	status_reset_basic_cb = undefined;
}

// Reset extra variables
// This is f**king stupid
function status_reset(status_reset_cb = null) {
	json.status_reset_basic(() => {
		status.bluetooth = status_bluetooth_default.apply();
		status.lights    = status_lights_default.apply();
		status.mid       = status_mid_default.apply();
		status.power     = status_power_default.apply();

		log.msg('Reset all status');

		typeof status_reset_cb === 'function' && process.nextTick(status_reset_cb);
		status_reset_cb = undefined;
	});
}

function init_listeners() {
	// Reset/write JSON data on power lib events, if configured
	update.on('status.power.active', (data) => {
		switch (data.new) {
			case false : {
				// Set modules as not ready
				if (config.json.reset_on_poweroff) json.modules_reset();

				// Write JSON config and status files
				if (config.json.write_on_poweroff) json.write();

				break;
			}

			case true : {
				// Write JSON config and status files
				if (config.json.write_on_run) json.write();
			}
		}
	});

	// Reset basic vars on server connection interruption
	update.on('status.server.connected', (data) => {
		if (data.new === false) json.status_reset_basic();
	});

	log.msg('Initialized listeners');
}

module.exports = {
	config_read        : config_read,
	config_write       : config_write,
	init_listeners     : init_listeners,
	modules_reset      : modules_reset,
	read               : read,
	reset              : reset,
	status_read        : status_read,
	status_reset       : status_reset,
	status_reset_basic : status_reset_basic,
	status_write       : status_write,
	write              : write,
};
<commit_msg>Update<commit_after>const write_options = { spaces : '\t' };

const defaults = require('defaults-deep');
const jsonfile = require('jsonfile');

const file_config = app_path + '/config.json';
const file_status = app_path + '/status.json';

const config_default = require('config-default');
const status_default = require('status-default');

const status_bluetooth_default = require('status-bluetooth-default');
const status_lights_default    = require('status-lights-default');
const status_mid_default       = require('status-mid-default');
const status_power_default     = require('status-power-default');

// Read config+status
async function read(read_cb = null) {
	// read JSON config file
	await json.config_read();

	// read JSON status file
	await json.status_read();

	// Execute callback
	typeof read_cb === 'function' && await read_cb();
	read_cb = null;
}

// Write config+status
async function write(write_cb = null) {
	// Write JSON config file
	await json.config_write();

	// Write JSON status file
	await json.status_write();

	// Execute callback
	typeof write_cb === 'function' && await write_cb();
	write_cb = null;
}

// Reset both modules and status vars
function reset(reset_cb = null) {
	json.modules_reset(() => { // Set modules as not ready
		json.status_reset(() => { // Reset some variables
			switch (config.json.write_on_reset) {
				case false : {
					typeof reset_cb === 'function' && process.nextTick(reset_cb);
					reset_cb = undefined;

					break;
				}

				default : {
					json.write(() => { // Write JSON files
						typeof reset_cb === 'function' && process.nextTick(reset_cb);
						reset_cb = undefined;
					});
				}
			}
		});
	});
}

// Read config JSON
async function config_read(config_read_cb = null) {
	let config_data;

	try {
		config_data = await jsonfile.readFileSync(file_config);
	}
	catch (err) {
		log.msg('Failed reading config, applying default config');

		config = config_default;
		await json.config_write(config_read_cb);
		return false;
	}

	// Lay the default values on top of the read object, in case new values were added
	config = await defaults(config_data, config_default);

	log.msg('Read config');

	typeof config_read_cb === 'function' && await config_read_cb();
	config_read_cb = undefined;
}

// Read status JSON
async function status_read(status_read_cb = null) {
	let status_data;

	try {
		status_data = await jsonfile.readFileSync(file_status);
	}
	catch (err) {
		log.msg('Failed reading status, applying default status');

		status = status_default;
		await json.status_write(status_read_cb);
		return false;
	}

	// Lay the default values on top of the read object, in case new values were added
	status = await defaults(status_data, status_default);

	log.msg('Read status');

	typeof status_read_cb === 'function' && await status_read_cb();
	status_read_cb = undefined;
}

// Write config JSON
async function config_write(config_write_cb = null) {
	// Don't write if empty
	if (typeof config.system === 'undefined') {
		log.msg('Failed writing config, config object empty');

		if (typeof config_write_cb !== 'function') return;
		await config_write_cb();
		config_write_cb = undefined;

		return;
	}

	try {
		await jsonfile.writeFileSync(file_config, config, write_options);
	}
	catch (err) {
		log.msg('Failed writing config');

		if (typeof config_write_cb !== 'function') return;
		await config_write_cb();
		config_write_cb = undefined;

		return false;
	}

	await log.msg('Wrote config');

	if (typeof config_write_cb !== 'function') return;
	await config_write_cb();
	config_write_cb = undefined;
}

// Write status JSON
async function status_write(status_write_cb = null) {
	// Don't write if empty
	if (typeof status.system === 'undefined') {
		log.msg('Failed writing status, status object empty');

		if (typeof status_write_cb !== 'function') return;
		await status_write_cb();
		status_write_cb = undefined;

		return;
	}

	try {
		await jsonfile.writeFileSync(file_status, status, write_options);
	}
	catch (err) {
		log.msg('Failed writing status');

		if (typeof status_write_cb !== 'function') return;
		await status_write_cb();
		status_write_cb = undefined;

		return false;
	}

	await log.msg('Wrote status');

	if (typeof status_write_cb !== 'function') return;
	await status_write_cb();
	status_write_cb = undefined;
}

// Set modules as not ready
function modules_reset(modules_reset_cb = null) {
	for (let module in bus.modules.modules) {
		module = module.toLowerCase();

		// Skip modules without entry in status object
		if (typeof status[module] === 'undefined') continue;
		if (status[module]        === null)        continue;

		switch (module) {
			case 'dia' : break;
			case 'glo' : break;
			case 'loc' : break;

			default : {
				status[module].reset = true;
				status[module].ready = false;
			}
		}
	}

	status.rad.source_name = 'off';

	log.msg('Reset modules');

	typeof modules_reset_cb === 'function' && process.nextTick(modules_reset_cb);
	modules_reset_cb = undefined;
}

// Reset basic variables
function status_reset_basic(status_reset_basic_cb = null) {
	status.engine.running = false;

	status.vehicle.handbrake      = false;
	status.vehicle.ignition       = 'off';
	status.vehicle.ignition_level = 0;
	status.vehicle.reverse        = false;

	log.msg('Reset basic status');

	typeof status_reset_basic_cb === 'function' && process.nextTick(status_reset_basic_cb);
	status_reset_basic_cb = undefined;
}

// Reset extra variables
// This is f**king stupid
function status_reset(status_reset_cb = null) {
	json.status_reset_basic(() => {
		status.bluetooth = status_bluetooth_default.apply();
		status.lights    = status_lights_default.apply();
		status.mid       = status_mid_default.apply();
		status.power     = status_power_default.apply();

		status.dsp = {
			echo      : null,
			m_audio   : null,
			mode      : null,
			ready     : false,
			reset     : true,
			room_size : null,
			eq        : {
				band0 : null,
				band1 : null,
				band2 : null,
				band3 : null,
				band4 : null,
				band5 : null,
				band6 : null,
			},
		};

		status.rad = {
			ready : false,
			reset : true,

			balance : 0,
			bass    : 0,
			dsp0    : 0,
			dsp1    : 0,
			fader   : 0,
			treble  : 0,

			source      : 0,
			source_name : 'off',
		};

		log.msg('Reset all status');

		typeof status_reset_cb === 'function' && process.nextTick(status_reset_cb);
		status_reset_cb = undefined;
	});
}

function init_listeners() {
	// Reset/write JSON data on power lib events, if configured
	update.on('status.power.active', (data) => {
		switch (data.new) {
			case false : {
				// Set modules as not ready
				if (config.json.reset_on_poweroff) json.modules_reset();

				// Write JSON config and status files
				if (config.json.write_on_poweroff) json.write();

				break;
			}

			case true : {
				// Write JSON config and status files
				if (config.json.write_on_run) json.write();
			}
		}
	});

	// Reset basic vars on server connection interruption
	update.on('status.server.connected', (data) => {
		if (data.new === false) json.status_reset_basic();
	});

	log.msg('Initialized listeners');
}

module.exports = {
	config_read        : config_read,
	config_write       : config_write,
	init_listeners     : init_listeners,
	modules_reset      : modules_reset,
	read               : read,
	reset              : reset,
	status_read        : status_read,
	status_reset       : status_reset,
	status_reset_basic : status_reset_basic,
	status_write       : status_write,
	write              : write,
};
<|endoftext|>


<commit_before>var React = require('react');
var D = React.DOM;

var uid = require('./uid');
var type = require('./type');

var Highlighter = require('./highlighter');
var highlighter = React.createFactory(Highlighter);

var PATH_PREFIX = '.root.';

var Leaf = React.createClass({
    getInitialState: function() {
        return {
            expanded: this._isInitiallyExpanded()
        };
    },
    getDefaultProps: function() {
        return {
            root: false,
            prefix: ''
        };
    },
    render: function() {
        var id = 'id_' + uid();
        var p = this.props;

        var d = {
            path: this.keypath(),
            key: p.label.toString(),
            value: p.data
        };

        var onLabelClick = this._onClick.bind(this, d);

        return D.div({ className: this.getClassName(), id: 'leaf-' + this._rootPath() },
            D.input({ className: 'json-inspector__radio', type: 'radio', name: p.id, id: id, tabIndex: -1 }),
            D.label({ className: 'json-inspector__line', htmlFor: id, onClick: onLabelClick },
                D.div({ className: 'json-inspector__flatpath' },
                    d.path),
                D.span({ className: 'json-inspector__key' },
                    this.format(d.key),
                    ':',
                    this.renderInteractiveLabel(d.key, true)),
                this.renderTitle(),
                this.renderShowOriginalButton()),
            this.renderChildren());
    },
    renderTitle: function() {
        var data = this.data();
        var t = type(data);

        switch (t) {
            case 'Array':
                return D.span({ className: 'json-inspector__value json-inspector__value_helper' },
                    '[] ' + items(data.length));
            case 'Object':
                return D.span({ className: 'json-inspector__value json-inspector__value_helper' },
                    '{} ' + items(Object.keys(data).length));
            default:
                return D.span({ className: 'json-inspector__value json-inspector__value_' + t.toLowerCase() },
                    this.format(String(data)),
                    this.renderInteractiveLabel(data, false));
        }
    },
    renderChildren: function() {
        var p = this.props;
        var childPrefix = this._rootPath();
        var data = this.data();

        if (this.state.expanded && !isPrimitive(data)) {
            return Object.keys(data).map(function(key) {
                return leaf({
                    data: data[key],
                    label: key,
                    prefix: childPrefix,
                    onClick: p.onClick,
                    id: p.id,
                    query: p.query,
                    getOriginal: this.state.original ? null : p.getOriginal,
                    key: key,
                    isExpanded: p.isExpanded,
                    interactiveLabel: p.interactiveLabel
                });
            }, this);
        }

        return null;
    },
    renderShowOriginalButton: function() {
        var p = this.props;

        if (isPrimitive(p.data) || this.state.original || !p.getOriginal || !p.query || contains(this.keypath(), p.query)) {
            return null;
        }

        return D.span({
            className: 'json-inspector__show-original',
            onClick: this._onShowOriginalClick
        });
    },
    renderInteractiveLabel: function(originalValue, isKey) {
        if (typeof this.props.interactiveLabel === 'function') {
            return this.props.interactiveLabel({
                // The distinction between `value` and `originalValue` is
                // provided to have backwards compatibility.
                value: String(originalValue),
                originalValue: originalValue,
                isKey: isKey,
                keypath: this.keypath()
            });
        }

        return null;
    },
    componentWillReceiveProps: function(p) {
        if (p.query) {
            this.setState({
                expanded: !contains(p.label, p.query)
            });
        } else if (!p.root) {
            this.setState({
                expanded: false
            });
        }
    },
    _rootPath: function() {
        return this.props.prefix + '.' + this.props.label;
    },
    keypath: function() {
        return this._rootPath().substr(PATH_PREFIX.length);
    },
    data: function() {
        return this.state.original || this.props.data;
    },
    format: function(string) {
        return highlighter({
            string: string,
            highlight: this.props.query
        });
    },
    getClassName: function() {
        var cn = 'json-inspector__leaf';

        if (this.props.root) {
            cn += ' json-inspector__leaf_root';
        }

        if (this.state.expanded) {
            cn += ' json-inspector__leaf_expanded';
        }

        if (!isPrimitive(this.props.data)) {
            cn += ' json-inspector__leaf_composite';
        }

        return cn;
    },
    toggle: function() {
        this.setState({
            expanded: !this.state.expanded
        });
    },
    _onClick: function(data, e) {
        this.toggle();
        this.props.onClick(data);

        e.stopPropagation();
    },
    _onShowOriginalClick: function(e) {
        this.setState({
            original: this.props.getOriginal(this.keypath())
        });

        e.stopPropagation();
    },
    _isInitiallyExpanded: function() {
        var p = this.props;
        var keypath = this.keypath();

        if (p.root) {
            return true;
        }

        if (p.query === '') {
            return p.isExpanded(keypath, p.data);
        } else {
            // When a search query is specified, first check if the keypath
            // contains the search query: if it does, then the current leaf
            // is itself a search result and there is no need to expand further.
            //
            // Having a `getOriginal` function passed signalizes that current
            // leaf only displays a subset of data, thus should be rendered
            // expanded to reveal the children that is being searched for.
            return !contains(keypath, p.query) && (typeof p.getOriginal === 'function');
        }
    }
});

// FIXME: There should be a better way to call a component factory from inside
// component definition.
var leaf = React.createFactory(Leaf);

function items(count) {
    return count + (count === 1 ? ' item' : ' items');
}

function contains(string, substring) {
    return string.indexOf(substring) !== -1;
}

function isPrimitive(value) {
    var t = type(value);
    return t !== 'Object' && t !== 'Array';
}

module.exports = Leaf;
<commit_msg>Assign correct key to leaf node<commit_after>var React = require('react');
var D = React.DOM;

var uid = require('./uid');
var type = require('./type');

var Highlighter = require('./highlighter');
var highlighter = React.createFactory(Highlighter);

var PATH_PREFIX = '.root.';

var Leaf = React.createClass({
    getInitialState: function() {
        return {
            expanded: this._isInitiallyExpanded(this.props)
        };
    },
    getDefaultProps: function() {
        return {
            root: false,
            prefix: ''
        };
    },
    render: function() {
        var id = 'id_' + uid();
        var p = this.props;

        var d = {
            path: this.keypath(),
            key: p.label.toString(),
            value: p.data
        };

        var onLabelClick = this._onClick.bind(this, d);

        return D.div({ className: this.getClassName(), id: 'leaf-' + this._rootPath() },
            D.input({ className: 'json-inspector__radio', type: 'radio', name: p.id, id: id, tabIndex: -1 }),
            D.label({ className: 'json-inspector__line', htmlFor: id, onClick: onLabelClick },
                D.div({ className: 'json-inspector__flatpath' },
                    d.path),
                D.span({ className: 'json-inspector__key' },
                    this.format(d.key),
                    ':',
                    this.renderInteractiveLabel(d.key, true)),
                this.renderTitle(),
                this.renderShowOriginalButton()),
            this.renderChildren());
    },
    renderTitle: function() {
        var data = this.data();
        var t = type(data);

        switch (t) {
            case 'Array':
                return D.span({ className: 'json-inspector__value json-inspector__value_helper' },
                    '[] ' + items(data.length));
            case 'Object':
                return D.span({ className: 'json-inspector__value json-inspector__value_helper' },
                    '{} ' + items(Object.keys(data).length));
            default:
                return D.span({ className: 'json-inspector__value json-inspector__value_' + t.toLowerCase() },
                    this.format(String(data)),
                    this.renderInteractiveLabel(data, false));
        }
    },
    renderChildren: function() {
        var p = this.props;
        var childPrefix = this._rootPath();
        var data = this.data();

        if (this.state.expanded && !isPrimitive(data)) {
            return Object.keys(data).map(function(key) {
                var value = data[key];

                return leaf({
                    data: value,
                    label: key,
                    prefix: childPrefix,
                    onClick: p.onClick,
                    id: p.id,
                    query: p.query,
                    getOriginal: this.state.original ? null : p.getOriginal,
                    key: getLeafKey(key, value),
                    isExpanded: p.isExpanded,
                    interactiveLabel: p.interactiveLabel
                });
            }, this);
        }

        return null;
    },
    renderShowOriginalButton: function() {
        var p = this.props;

        if (isPrimitive(p.data) || this.state.original || !p.getOriginal || !p.query || contains(this.keypath(), p.query)) {
            return null;
        }

        return D.span({
            className: 'json-inspector__show-original',
            onClick: this._onShowOriginalClick
        });
    },
    renderInteractiveLabel: function(originalValue, isKey) {
        if (typeof this.props.interactiveLabel === 'function') {
            return this.props.interactiveLabel({
                // The distinction between `value` and `originalValue` is
                // provided to have backwards compatibility.
                value: String(originalValue),
                originalValue: originalValue,
                isKey: isKey,
                keypath: this.keypath()
            });
        }

        return null;
    },
    componentWillReceiveProps: function(p) {
        if (p.query) {
            this.setState({
                expanded: !contains(p.label, p.query)
            });
        // FIXME: This looks like an unnecessary state reset, figure out
        // what happens when removed.
        } else if (!p.root) {
            this.setState({
                expanded: this._isInitiallyExpanded(p)
            });
        }
    },
    _rootPath: function() {
        return this.props.prefix + '.' + this.props.label;
    },
    keypath: function() {
        return this._rootPath().substr(PATH_PREFIX.length);
    },
    data: function() {
        return this.state.original || this.props.data;
    },
    format: function(string) {
        return highlighter({
            string: string,
            highlight: this.props.query
        });
    },
    getClassName: function() {
        var cn = 'json-inspector__leaf';

        if (this.props.root) {
            cn += ' json-inspector__leaf_root';
        }

        if (this.state.expanded) {
            cn += ' json-inspector__leaf_expanded';
        }

        if (!isPrimitive(this.props.data)) {
            cn += ' json-inspector__leaf_composite';
        }

        return cn;
    },
    toggle: function() {
        this.setState({
            expanded: !this.state.expanded
        });
    },
    _onClick: function(data, e) {
        this.toggle();
        this.props.onClick(data);

        e.stopPropagation();
    },
    _onShowOriginalClick: function(e) {
        this.setState({
            original: this.props.getOriginal(this.keypath())
        });

        e.stopPropagation();
    },
    _isInitiallyExpanded: function(p) {
        var keypath = this.keypath();

        if (p.root) {
            return true;
        }

        if (p.query === '') {
            return p.isExpanded(keypath, p.data);
        } else {
            // When a search query is specified, first check if the keypath
            // contains the search query: if it does, then the current leaf
            // is itself a search result and there is no need to expand further.
            //
            // Having a `getOriginal` function passed signalizes that current
            // leaf only displays a subset of data, thus should be rendered
            // expanded to reveal the children that is being searched for.
            return !contains(keypath, p.query) && (typeof p.getOriginal === 'function');
        }
    }
});

// FIXME: There should be a better way to call a component factory from inside
// component definition.
var leaf = React.createFactory(Leaf);

function items(count) {
    return count + (count === 1 ? ' item' : ' items');
}

function getLeafKey(key, value) {
    if (isPrimitive(value)) {
        return key + ':' + value;
    } else {
        return key + '[' + type(value) + ']';
    }
}

function contains(string, substring) {
    return string.indexOf(substring) !== -1;
}

function isPrimitive(value) {
    var t = type(value);
    return t !== 'Object' && t !== 'Array';
}

module.exports = Leaf;
<|endoftext|>


<commit_before>angular.module('angular-login', [
  // login service
  'loginService',
  //'angular-login.mock',
  'angular-login.directives',
  // different app sections
  'angular-login.home',
  'angular-login.recyclage',
  'angular-login.stats',
  'angular-login.competences',
  'angular-login.pages',
  'angular-login.benevoles',
  'angular-login.benevolesadmin',
  'angular-login.register',
  'angular-login.error',
  'angular-services.competence',
  // components
  'ngAnimate'
])
  .config(function ($urlRouterProvider, $httpProvider) {
    $urlRouterProvider.otherwise('/');
    $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
  })
  .run(function ($rootScope, $window) {
    $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams) {
      var realURL = toState.url;
      if (!!$window.ga) {
        // resolves variables inside urls, ex: /error/:error in /error/unauthorized
        for (var v in toParams) {
          realURL = realURL.replace(':' + v, toParams[v]);
        }
        $window.ga('send', 'pageview', realURL);
      }
    });
    /**
     * $rootScope.doingResolve is a flag useful to display a spinner on changing states.
     * Some states may require remote data so it will take awhile to load.
     */
    var resolveDone = function () { $rootScope.doingResolve = false; };
    $rootScope.doingResolve = false;

    $rootScope.$on('$stateChangeStart', function () {
      $rootScope.doingResolve = true;
    });
    $rootScope.$on('$stateChangeSuccess', resolveDone);
    $rootScope.$on('$stateChangeError', resolveDone);
    $rootScope.$on('$statePermissionError', resolveDone);
  })
  .controller('BodyController', function ($scope, $state, $stateParams, loginService, $http, $timeout, $log) {
    // Expose $state and $stateParams to the <body> tag
    $scope.$state = $state;
    $scope.$stateParams = $stateParams;
    $scope.url = url_ws_pegass;

    // loginService exposed and a new Object containing login user/pwd
    $scope.ls = loginService;
    $scope.login = {
      working: false,
      wrong: false
    };

    $scope.loginMe = function () {

      if ($scope.ls.inLocalStorage == false) {
        // setup promise, and 'working' flag
        var url_connect = 'http://' + $scope.url + '/connect?username=' + $scope.login.username + '&password=' + $scope.login.password;
        $log.info(url_connect);
        var loginPromise = $http.get(url_connect, $scope.login);

        $scope.login.working = true;
        $scope.login.wrong = false;

        loginService.loginUser(loginPromise);
        loginPromise.error(function () {
          $scope.login.wrong = true;
          $timeout(function () { $scope.login.wrong = false; }, 8000);
        });
        loginPromise.finally(function () {
          $scope.login.working = false;
          $scope.ls.setToken();
        });
      }
      else {
        var url_connect = 'http://' + $scope.url + '/connecttest?F5_ST=' + $scope.ls.F5_ST + '&LastMRH_Session=' + $scope.ls.LastMRH_Session + '&MRHSession=' + $scope.ls.MRHSession;
        $log.info(url_connect);
        var loginPromise = $http.get(url_connect, $scope.login);

        $scope.login.working = true;
        $scope.login.wrong = false;

        loginService.loginUser(loginPromise);
        loginPromise.error(function () {
          $scope.login.wrong = true;
          $timeout(function () { $scope.login.wrong = false; }, 8000);
          loginService.F5_ST = null;
          loginService.MRHSession = null;
          loginService.LastMRH_Session = null;
          loginService.setToken();
        });
        loginPromise.finally(function () {
          $scope.login.working = false;
        });
      }
    };

    $scope.logoutMe = function () {
      loginService.logoutUser($http.get('/#/logout'));
    };
  });
<commit_msg>solve error in login<commit_after>angular.module('angular-login', [
  // login service
  'loginService',
  //'angular-login.mock',
  'angular-login.directives',
  // different app sections
  'angular-login.home',
  'angular-login.recyclage',
  'angular-login.stats',
  'angular-login.competences',
  'angular-login.pages',
  'angular-login.benevoles',
  'angular-login.benevolesadmin',
  'angular-login.register',
  'angular-login.error',
  'angular-services.competence',
  // components
  'ngAnimate'
])
  .config(function ($urlRouterProvider, $httpProvider) {
    $urlRouterProvider.otherwise('/');
    $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
  })
  .run(function ($rootScope, $window) {
    $rootScope.$on('$stateChangeSuccess', function (event, toState, toParams) {
      var realURL = toState.url;
      if (!!$window.ga) {
        // resolves variables inside urls, ex: /error/:error in /error/unauthorized
        for (var v in toParams) {
          realURL = realURL.replace(':' + v, toParams[v]);
        }
        $window.ga('send', 'pageview', realURL);
      }
    });
    /**
     * $rootScope.doingResolve is a flag useful to display a spinner on changing states.
     * Some states may require remote data so it will take awhile to load.
     */
    var resolveDone = function () { $rootScope.doingResolve = false; };
    $rootScope.doingResolve = false;

    $rootScope.$on('$stateChangeStart', function () {
      $rootScope.doingResolve = true;
    });
    $rootScope.$on('$stateChangeSuccess', resolveDone);
    $rootScope.$on('$stateChangeError', resolveDone);
    $rootScope.$on('$statePermissionError', resolveDone);
  })
  .controller('BodyController', function ($scope, $state, $stateParams, loginService, $http, $timeout, $log) {
    // Expose $state and $stateParams to the <body> tag
    $scope.$state = $state;
    $scope.$stateParams = $stateParams;
    $scope.url = url_ws_pegass;

    // loginService exposed and a new Object containing login user/pwd
    $scope.ls = loginService;
    $scope.login = {
      working: false,
      wrong: false
    };

    $scope.loginMe = function () {

      if ($scope.ls.inLocalStorage == false) {
        // setup promise, and 'working' flag
        var url_connect = 'http://' + $scope.url + '/connect?username=' + $scope.login.username + '&password=' + $scope.login.password;
        $log.info(url_connect);
        var loginPromise = $http.get(url_connect, $scope.login);

        $scope.login.working = true;
        $scope.login.wrong = false;

        loginService.loginUser(loginPromise);
        loginPromise.error(function () {
          $scope.login.wrong = true;
          $timeout(function () { $scope.login.wrong = false; }, 8000);
        });
        loginPromise.finally(function () {
          $scope.login.working = false;
          $scope.ls.setToken();
        });
      }
      else {
        var url_connect = 'http://' + $scope.url + '/connecttest?F5_ST=' + $scope.ls.F5_ST + '&LastMRH_Session=' + $scope.ls.LastMRH_Session + '&MRHSession=' + $scope.ls.MRHSession;
        $log.info(url_connect);
        var loginPromise = $http.get(url_connect, $scope.login);

        $scope.login.working = true;
        $scope.login.wrong = false;

        loginService.loginUser(loginPromise);
        loginPromise.error(function () {
          $scope.login.wrong = true;
          $timeout(function () { $scope.login.wrong = false; }, 8000);
          loginService.F5_ST = null;
          loginService.MRHSession = null;
          loginService.LastMRH_Session = null;
          loginService.setToken();
        });
        loginPromise.finally(function () {
          $scope.login.working = false;
        });
      }
    };

    $scope.logoutMe = function () {
      loginService.logoutUser($http.get('/#/logout'));
    };

    if ($scope.ls.inLocalStorage == true) {
      $scope.loginMe();
    }
  });
<|endoftext|>


<commit_before>
// link with no args: symlink the folder to the global location
// link with package arg: symlink the global to the local

var npm = require("../npm")
  , symlink = require("./utils/link")
  , fs = require("./utils/graceful-fs")
  , log = require("./utils/log")
  , asyncMap = require("./utils/async-map")
  , chain = require("./utils/chain")
  , path = require("path")
  , relativize = require("./utils/relativize")
  , rm = require("./utils/rm-rf")
  , output = require("./utils/output")

module.exports = link

link.usage = "npm link (in package dir)"
           + "\nnpm link <pkg> (link global into local)"

function link (args, cb) {
  if (npm.config.get("global")) {
    return cb(new Error("link should never be --global."))
  }
  if (args.length) return linkInstall(args, cb)
  linkPkg(npm.prefix, cb)
}

function linkInstall (pkgs, cb) {
  var gp = npm.config.get("prefix")
  asyncMap(pkgs, function (pkg, cb) {
    var pp = path.resolve(gp, "node_modules", pkg)
      , rp = null
      , target = path.resolve(npm.dir, pkg)
    fs.lstat(pp, function (er, st) {
      if (er) {
        log.error(pkg, "not installed globally")
        next()
      } else if (!st.isSymbolicLink()) {
        log.warn(pkg, "not a symbolic link")
        rp = pp
        next()
      } else {
        return fs.realpath(pp, function (er, real) {
          if (er) log.warn(pkg, "invalid symbolic link")
          else rp = real
          next()
        })
      }
    })

    function next () {
      chain
        ( [npm.commands, "unbuild", [target]]
        , [symlink, pp, target]
        , rp && [npm.commands, "build", [target]]
        , [ resultPrinter, pkg, pp, target, rp ]
        , cb )
    }
  }, cb)
}

function linkPkg (folder, cb) {
  var gp = npm.config.get("prefix")
    , me = npm.prefix
    , target = path.resolve(gp, "node_modules", path.basename(me))
  rm(target, function (er) {
    if (er) return cb(er)
    symlink(me, target, function (er) {
      if (er) return cb(er)
      npm.commands.build([target], function (er) {
        if (er) return cb(er)
        resultPrinter(path.basename(me), me, target, cb)
      })
    })
  })
}

function resultPrinter (pkg, src, dest, rp, cb) {
  if (typeof cb !== "function") cb = rp, rp = null
  var where = relativize(dest, path.resolve(process.cwd(),"x"))
  rp = (rp || "").trim()
  src = (src || "").trim()
  if (rp === src) rp = null
  output.write(where+"@ -> "+(src.trim())
              +(rp ? "@ -> "+rp: ""), cb)
}
<commit_msg>completion for link<commit_after>
// link with no args: symlink the folder to the global location
// link with package arg: symlink the global to the local

var npm = require("../npm")
  , symlink = require("./utils/link")
  , fs = require("./utils/graceful-fs")
  , log = require("./utils/log")
  , asyncMap = require("./utils/async-map")
  , chain = require("./utils/chain")
  , path = require("path")
  , relativize = require("./utils/relativize")
  , rm = require("./utils/rm-rf")
  , output = require("./utils/output")

module.exports = link

link.usage = "npm link (in package dir)"
           + "\nnpm link <pkg> (link global into local)"

link.completion = function (opts, cb) {
  var dir = path.join(npm.config.get("prefix"), "node_modules")
  fs.readdir(dir, function (er, files) {
    cb(er, files.filter(function (f) {
      return f.charAt(0) !== "."
    }))
  })
}

function link (args, cb) {
  if (npm.config.get("global")) {
    return cb(new Error("link should never be --global."))
  }
  if (args.length) return linkInstall(args, cb)
  linkPkg(npm.prefix, cb)
}

function linkInstall (pkgs, cb) {
  var gp = npm.config.get("prefix")
  asyncMap(pkgs, function (pkg, cb) {
    var pp = path.resolve(gp, "node_modules", pkg)
      , rp = null
      , target = path.resolve(npm.dir, pkg)
    fs.lstat(pp, function (er, st) {
      if (er) {
        log.error(pkg, "not installed globally")
        next()
      } else if (!st.isSymbolicLink()) {
        log.warn(pkg, "not a symbolic link")
        rp = pp
        next()
      } else {
        return fs.realpath(pp, function (er, real) {
          if (er) log.warn(pkg, "invalid symbolic link")
          else rp = real
          next()
        })
      }
    })

    function next () {
      chain
        ( [npm.commands, "unbuild", [target]]
        , [symlink, pp, target]
        , rp && [npm.commands, "build", [target]]
        , [ resultPrinter, pkg, pp, target, rp ]
        , cb )
    }
  }, cb)
}

function linkPkg (folder, cb) {
  var gp = npm.config.get("prefix")
    , me = npm.prefix
    , target = path.resolve(gp, "node_modules", path.basename(me))
  rm(target, function (er) {
    if (er) return cb(er)
    symlink(me, target, function (er) {
      if (er) return cb(er)
      npm.commands.build([target], function (er) {
        if (er) return cb(er)
        resultPrinter(path.basename(me), me, target, cb)
      })
    })
  })
}

function resultPrinter (pkg, src, dest, rp, cb) {
  if (typeof cb !== "function") cb = rp, rp = null
  var where = relativize(dest, path.resolve(process.cwd(),"x"))
  rp = (rp || "").trim()
  src = (src || "").trim()
  if (rp === src) rp = null
  output.write(where+"@ -> "+(src.trim())
              +(rp ? "@ -> "+rp: ""), cb)
}
<|endoftext|>


<commit_before>/**
 * This are just quick tests to get experience with Pebble.js
 */

var UI = require('ui');
var ajax = require('ajax');

// Create a Card with title and subtitle
var card = new UI.Card({
  title:'Chatty',
  subtitle:'Press right buttons...'
});

// Display the Card
card.show();

card.on('click', 'up', function(e) {
  ajax(
    {
      url: 'http://chatty-toedter.gigantic.io/api/buildinfo',
      type: 'json'
    },
    function(data) {
      var version = data.version;
      var timestamp = data.timeStamp;
      var menu = new UI.Menu({
        sections: [{
          items: [{
            title: 'Version',
            subtitle: version
          }, {
            title: 'Timestamp',
            subtitle: timestamp
          }]
        }]
      });
      menu.show();
    },
    function(error) {
      card.body('error getting Chatty buildinfo');
    }
  );
});

card.on('click', 'select', function(e) {
  ajax(
    {
      url: 'http://chatty-toedter.gigantic.io/api/messages?projection=excerpt',
      type: 'json'
    },
    function(data) {
      var messages = data._embedded['chatty:messages'];
      var myItems = [];

      for (var i = 0; i < messages.length; i++) {
        myItems[i] = {};
        myItems[i].title = messages[i].author.id;
        myItems[i].subtitle = messages[i].text;
      }

      var menu = new UI.Menu({
        sections: [{
          items: myItems
        }]
      });
      menu.show();
    },
    function(error) {
      card.body('error getting Chatty messages');
    }
  );
});

card.on('click', 'down', function(e) {
  ajax(
    {
      url: 'http://chatty-toedter.gigantic.io/api/users',
      type: 'json'
    },
    function(data) {
      var users = data._embedded['chatty:users'];
      var myItems = [];

      for (var i = 0; i < users.length; i++) {
        myItems[i] = {};
        myItems[i].title = users[i].fullName;
        myItems[i].subtitle = users[i].email;
      }

      var menu = new UI.Menu({
        sections: [{
          items: myItems
        }]
      });
      menu.show();
    },
    function(error) {
      card.body('error getting Chatty users');
    }
  );
});

<commit_msg>new main menu<commit_after>/**
 * This little Pebble app accesses the Chatty application,
 * see https://github.com/toedter/chatty
 */

var UI = require('ui');
var ajax = require('ajax');

var mainMenu = new UI.Menu({
  sections: [{
    title: 'Chatty',
    items: [{
       title: 'Messages'
    },{
       title: 'Users'
    },{
       title: 'Version'
    }]
  }]
});

mainMenu.show();

mainMenu.on('select', function(e) {
  console.log('Selected item #' + e.itemIndex + ' of section #' + e.sectionIndex);
  console.log('The item is titled "' + e.item.title + '"');
  switch(e.itemIndex) {
    case 0:
        showMessages();
        break;
    case 1:
        showUsers();
        break;
    default:
        showBuildInfo();
  }
});

function showBuildInfo() {
  ajax(
    {
      url: 'http://chatty-toedter.gigantic.io/api/buildinfo',
      type: 'json'
    },
    function(data) {
      var version = data.version;
      var timestamp = data.timeStamp;
      var menu = new UI.Menu({
        sections: [{
          items: [{
            title: 'Version',
            subtitle: version
          }, {
            title: 'Timestamp',
            subtitle: timestamp
          }]
        }]
      });
      menu.show();
    },
    function(error) {
      console.log('error getting Chatty buildinfo');
    }
  );
}

function showMessages() {
  ajax(
    {
      url: 'http://chatty-toedter.gigantic.io/api/messages?projection=excerpt',
      type: 'json'
    },
    function(data) {
      var messages = data._embedded['chatty:messages'];
      var myItems = [];

      for (var i = 0; i < messages.length; i++) {
        myItems[i] = {};
        myItems[i].title = messages[i].author.id;
        myItems[i].subtitle = messages[i].text;
      }

      var menu = new UI.Menu({
        sections: [{
          items: myItems
        }]
      });
      menu.show();
    },
    function(error) {
      console.log('error getting Chatty messages');
    }
  );
}

function showUsers() {
  ajax(
    {
      url: 'http://chatty-toedter.gigantic.io/api/users',
      type: 'json'
    },
    function(data) {
      var users = data._embedded['chatty:users'];
      var myItems = [];

      for (var i = 0; i < users.length; i++) {
        myItems[i] = {};
        myItems[i].title = users[i].fullName;
        myItems[i].subtitle = users[i].email;
      }

      var menu = new UI.Menu({
        sections: [{
          items: myItems
        }]
      });
      menu.show();
    },
    function(error) {
      console.log('error getting Chatty users');
    }
  );
}

<|endoftext|>