<commit_before>/*!
 * ProxyClient provides the basis for generating similar API clients.
 */
var http = require('http');
var https = require('https');
var url = require('url');
var util = require('util');
var express = require('express');
var mi = require('mi');
var sawmill = require('sawmill');
var superagent = require('superagent');
var superagentThen = require('superagent-then');
var when = require('when');

/**
 * Creates a new instance of ProxyClient with the provided `options`. The
 * available options are:
 *
 *  - `rootUrl`: The URL to base all requests on. Must include the protocol
 *    (http/https). Defaults to 'http://localhost'.
 *  - `logger`: An optional "bunyan-style" Logger instance to send logs to.
 *    More specifically, this object is expected to have a printf-like `info`
 *    method, which will be called to log each request/response. An Object
 *    with additional context will be passed-in as the first parameter.
 */
function ProxyClient(options) {
  if (!(this instanceof ProxyClient)) {
    return new ProxyClient(options);
  }

  options = options || {};

  this.rootUrl = this.rootUrl || options.rootUrl || 'http://localhost';
  this.logger = this.logger || options.logger || sawmill.createMill(this.constructor.name);
  this.timeout = this.timeout || options.timeout || 5000;

  this._authorization = null;
}
ProxyClient.extend = mi.extend;
ProxyClient.inherit = mi.inherit;

/**
 * Create a new instance of this Client type. See constructor for valid options.
 */
ProxyClient.createClient = function createClient(options) {
  var cls = this;
  return cls(options);
};

/**
 * Gets a child Client with the same settings as this Client beyond any
 * additional `options` specified.
 */
ProxyClient.prototype.getChild = function getChild(options) {
  var child = this.constructor.createClient(this);
  child._authorization = options.auth;
  return child;
};

/**
 * Gets a complete URL relative to the Client's `rootUrl`.
 */
ProxyClient.prototype.getUrl = function getUrl(path) {
  // If this is an absolute URL, use it as-is.
  if (url.parse(path).hostname) {
    return path;
  }

  return this.rootUrl + path;
};

/**
 * Creates a Promise-ready Superagent Request. For most requests:
 *
 * 1. `request.send()` should be used to provide a body.
 * 1. `request.end()` should be used to complete the request, returning a
 *   Promise to capture the response or error.
 *
 * See [https://github.com/visionmedia/superagent]() for more information on
 * the methods available to Requests.
 *
 * NOTE: A successfully-made request may not have been responded to with a
 * successful (200-ish) status code. Please check the status code in an
 * application-specific way after receiving the Response.
 */
ProxyClient.prototype.request = function request(method, path) {
  var self = this;
  var start = Date.now();
  var href = self.getUrl(path);

  return superagent(method, href)
    .set('Authorization', self._authorization || '')
    .timeout(self.timeout)
    .use(superagentThen)
    .on('request', function (req) {
      self.logger.info(self._formatRequest(req), '< %s %s', req.method, req.url);
    })
    .on('error', function (err) {
      self.logger.error('Error in %s %s: %s', method, href, err);
    })
    .on('response', function (res) {
      var ms = Date.now() - start;

      self.logger.info(self._formatResponse(res), '> %s %s %s %s ms', method, href, res.status, ms.toFixed(3));
    });
};

/**
 * Make a GET request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.get = function get(path) {
  return this.request('GET', path);
};

/**
 * Make a POST request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.post = function post(path) {
  return this.request('POST', path);
};

/**
 * Make a PUT request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.put = function put(path) {
  return this.request('PUT', path);
};

/**
 * Make a DELETE request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.del = function del(path) {
  return this.request('DELETE', path);
};

/**
 * Generates a Express-compatible sub-application that proxies requests from
 * browser clients.
 */
ProxyClient.prototype.subapp = function subapp() {
  var self = this;
  var app = express();

  app.use(function (req, res, next) {
    var start = Date.now();
    var href = self.getUrl(req.url);
    var parsedUrl = url.parse(href);
    var outgoing = self._createCoreRequest({
      protocol: parsedUrl.protocol,
      method: req.method,
      hostname: parsedUrl.hostname,
      port: parsedUrl.port,
      path: parsedUrl.path,
      headers: util._extend(req.headers, {
        'Connection': 'Keep-Alive',
        'Host': parsedUrl.host,
        'Origin': parsedUrl.host
      })
    });

    self.logger.info(self._formatRequest(req), '< %s %s', req.method, href);

    outgoing.on('response', function (incoming) {
      var ms = Date.now() - start;

      self.logger.info(self._formatResponse(incoming), '> %s %s %s %s ms', req.method, href, incoming.statusCode, ms.toFixed(3));

      res.status(incoming.statusCode);
      res.set(incoming.headers);
      incoming.pipe(res);
    });

    req.pipe(outgoing);
  });

  return app;
};

/**
 * Returns a Rejected Promise from the bad `response` with the following
 * strategy:
 *
 * - `message`: A "message" property of the response JSON, falling back to the
 *     response text.
 * - `code`: A "code" property of the response JSON, falling back to the status
 *     code.
 * - `name`: A "name" property of the repsonse JSON, falling back to the common
 *     name of the status code (e.g. BadRequestError).
 * - `response`: The original response, for context.
 */
ProxyClient.prototype.rejectResponse = function rejectResponse(response) {
  var body = response.body || {};
  var err = new Error(body.message || response.text);

  err.code = body.code || response.status;
  err.name = body.name || (http.STATUS_CODES[response.status].replace(/\s/g, '') + 'Error');
  err.response = response;

  return when.reject(err);
}

/**
 * Internal use only.
 *
 * Helper to create a core Request based on `options`. The only option not
 * used by Node core is `options.protocol`, which signals the core module to
 * use.
 */
ProxyClient.prototype._createCoreRequest = function _createCoreRequest(options) {
  if (options.protocol === 'http:') {
    return http.request(options);
  }

  if (options.protocol === 'https:') {
    return https.request(options);
  }

  throw new Error('Invalid protocol, ' + options.protocol + '. Check rootUrl.');
};

/**
 * Internal use only.
 *
 * Formats a Request for logging.
 */
ProxyClient.prototype._formatRequest = function _formatRequest(request) {
  var headers = request.headers || request.header || {};

  // Extra, Node-specific header location.
  if (request.req) {
    headers = request.req._headers;
  }

  return {
    method: request.method,
    url: request.url,
    headers: headers
  };
};

/**
 * Internal use only.
 *
 * Formats a Response for logging.
 */
ProxyClient.prototype._formatResponse = function _formatResponse(response) {
  return {
    status: response.status,
    headers: response.headers
  };
};

/*!
 * Export `ProxyClient`.
 */
module.exports = ProxyClient;
<commit_msg>Generalize header configuration.<commit_after>/*!
 * ProxyClient provides the basis for generating similar API clients.
 */
var http = require('http');
var https = require('https');
var url = require('url');
var util = require('util');
var express = require('express');
var mi = require('mi');
var sawmill = require('sawmill');
var superagent = require('superagent');
var superagentThen = require('superagent-then');
var when = require('when');

/**
 * Creates a new instance of ProxyClient with the provided `options`. The
 * available options are:
 *
 *  - `rootUrl`: The URL to base all requests on. Must include the protocol
 *    (http/https). Defaults to 'http://localhost'.
 *  - `logger`: An optional "bunyan-style" Logger instance to send logs to.
 *    More specifically, this object is expected to have a printf-like `info`
 *    method, which will be called to log each request/response. An Object
 *    with additional context will be passed-in as the first parameter.
 */
function ProxyClient(options) {
  if (!(this instanceof ProxyClient)) {
    return new ProxyClient(options);
  }

  options = options || {};

  this.rootUrl = this.rootUrl || options.rootUrl || 'http://localhost';
  this.logger = this.logger || options.logger || sawmill.createMill(this.constructor.name);
  this.timeout = this.timeout || options.timeout || 5000;

  this.headers = util._extend(this.headers || {}, options.headers);
}
ProxyClient.extend = mi.extend;
ProxyClient.inherit = mi.inherit;

/**
 * Create a new instance of this Client type. See constructor for valid options.
 */
ProxyClient.createClient = function createClient(options) {
  var cls = this;
  return cls(options);
};

/**
 * Gets a child Client with the same settings as this Client beyond any
 * additional `options` specified.
 */
ProxyClient.prototype.getChild = function getChild(options) {
  var child = this.constructor.createClient(this);

  if (options) {
    child.rootUrl = options.rootUrl || child.rootUrl;
    child.logger = options.logger || child.logger;
    child.timeout = options.timeout || child.timeout;
    child.headers = util._extend(child.headers, options.headers);
  }

  return child;
};

/**
 * Gets a complete URL relative to the Client's `rootUrl`.
 */
ProxyClient.prototype.getUrl = function getUrl(path) {
  // If this is an absolute URL, use it as-is.
  if (url.parse(path).hostname) {
    return path;
  }

  return this.rootUrl + path;
};

/**
 * Creates a Promise-ready Superagent Request. For most requests:
 *
 * 1. `request.send()` should be used to provide a body.
 * 1. `request.end()` should be used to complete the request, returning a
 *   Promise to capture the response or error.
 *
 * See [https://github.com/visionmedia/superagent]() for more information on
 * the methods available to Requests.
 *
 * NOTE: A successfully-made request may not have been responded to with a
 * successful (200-ish) status code. Please check the status code in an
 * application-specific way after receiving the Response.
 */
ProxyClient.prototype.request = function request(method, path) {
  var self = this;
  var start = Date.now();
  var href = self.getUrl(path);

  return superagent(method, href)
    .set(self.headers)
    .timeout(self.timeout)
    .use(superagentThen)
    .on('request', function (req) {
      self.logger.info(self._formatRequest(req), '< %s %s', req.method, req.url);
    })
    .on('error', function (err) {
      self.logger.error('Error in %s %s: %s', method, href, err);
    })
    .on('response', function (res) {
      var ms = Date.now() - start;

      self.logger.info(self._formatResponse(res), '> %s %s %s %s ms', method, href, res.status, ms.toFixed(3));
    });
};

/**
 * Make a GET request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.get = function get(path) {
  return this.request('GET', path);
};

/**
 * Make a POST request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.post = function post(path) {
  return this.request('POST', path);
};

/**
 * Make a PUT request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.put = function put(path) {
  return this.request('PUT', path);
};

/**
 * Make a DELETE request, returning a promise to be fulfilled with the Response
 * or rejected with an HTTP error. See `request` for more details.
 */
ProxyClient.prototype.del = function del(path) {
  return this.request('DELETE', path);
};

/**
 * Generates a Express-compatible sub-application that proxies requests from
 * browser clients.
 */
ProxyClient.prototype.subapp = function subapp() {
  var self = this;
  var app = express();

  app.use(function (req, res, next) {
    var start = Date.now();
    var href = self.getUrl(req.url);
    var parsedUrl = url.parse(href);
    var outgoing = self._createCoreRequest({
      protocol: parsedUrl.protocol,
      method: req.method,
      hostname: parsedUrl.hostname,
      port: parsedUrl.port,
      path: parsedUrl.path,
      headers: util._extend(req.headers, {
        'Connection': 'Keep-Alive',
        'Host': parsedUrl.host,
        'Origin': parsedUrl.host
      })
    });

    self.logger.info(self._formatRequest(req), '< %s %s', req.method, href);

    outgoing.on('response', function (incoming) {
      var ms = Date.now() - start;

      self.logger.info(self._formatResponse(incoming), '> %s %s %s %s ms', req.method, href, incoming.statusCode, ms.toFixed(3));

      res.status(incoming.statusCode);
      res.set(incoming.headers);
      incoming.pipe(res);
    });

    req.pipe(outgoing);
  });

  return app;
};

/**
 * Returns a Rejected Promise from the bad `response` with the following
 * strategy:
 *
 * - `message`: A "message" property of the response JSON, falling back to the
 *     response text.
 * - `code`: A "code" property of the response JSON, falling back to the status
 *     code.
 * - `name`: A "name" property of the repsonse JSON, falling back to the common
 *     name of the status code (e.g. BadRequestError).
 * - `response`: The original response, for context.
 */
ProxyClient.prototype.rejectResponse = function rejectResponse(response) {
  var body = response.body || {};
  var err = new Error(body.message || response.text);

  err.code = body.code || response.status;
  err.name = body.name || (http.STATUS_CODES[response.status].replace(/\s/g, '') + 'Error');
  err.response = response;

  return when.reject(err);
}

/**
 * Internal use only.
 *
 * Helper to create a core Request based on `options`. The only option not
 * used by Node core is `options.protocol`, which signals the core module to
 * use.
 */
ProxyClient.prototype._createCoreRequest = function _createCoreRequest(options) {
  if (options.protocol === 'http:') {
    return http.request(options);
  }

  if (options.protocol === 'https:') {
    return https.request(options);
  }

  throw new Error('Invalid protocol, ' + options.protocol + '. Check rootUrl.');
};

/**
 * Internal use only.
 *
 * Formats a Request for logging.
 */
ProxyClient.prototype._formatRequest = function _formatRequest(request) {
  var headers = request.headers || request.header || {};

  // Extra, Node-specific header location.
  if (request.req) {
    headers = request.req._headers;
  }

  return {
    method: request.method,
    url: request.url,
    headers: headers
  };
};

/**
 * Internal use only.
 *
 * Formats a Response for logging.
 */
ProxyClient.prototype._formatResponse = function _formatResponse(response) {
  return {
    status: response.status,
    headers: response.headers
  };
};

/*!
 * Export `ProxyClient`.
 */
module.exports = ProxyClient;
<|endoftext|>


<commit_before>'use strict';

//const recast = require('./botlogic/recast.js');
const apiai = require('./../botlogic/apiai.js');
const facebook = require('./../channels/facebook.js');
const telegram = require('./../channels/telegram.js');
const aslan = require('./../channels/aslan-messenger.js');
const pr = require('./processing.js');
const fd = require('./field.js');

var messageReceived;

/*
*   Fonction appelée par les channels lorsque l'on reçoit un message
*/
function receivedMessage(message) {
    messageReceived = message;
    if(message.location != undefined) {
        getLastIntent(message);
    } else {
        runLogicLayer(message);
    }
}

/*
*   Fonction qu lance la couche logique avec NLP
*/
function runLogicLayer(message) {
    /*botlogic.defineCallback(callbackLogicLayer);
    if(message.senderID != undefined && message.text != undefined) {
        botlogic.sendMessage(message.text, `session-${message.senderID}`, {});
    }*/
    /*recast.sendMessage(message.text, callbackLogicLayer);*/
    apiai.sendMessage(message.senderID, message.text, callbackLogicLayer)
}

/*
*   Fonction de callback appelée par la couche logique
*/
function callbackLogicLayer(response) {
    console.log("APIAI sended : ", JSON.stringify(response));
    var intent = response.result.metadata.intentName;
    processing(intent, response);
}

/*
*   Fonction qui traite le message en fonction du contexte du message
*   La fonction renvoie la réponse à la channel
*/
function processing(intent, response) {
    switch(intent) {
        case "bonjour" :
            pr.processingGrettings(messageReceived, response);
            break;
        case "heure" :
            pr.processingHour(response);
            break;
        case "fontaine" :
            pr.processingFountain(response);
            break;
        case "habitant":
            pr.processingCitizen(response);
            break;
        case "jour":
            pr.processingDate(response);
            break;
        case "meteo":
            pr.processingWeather(response);
            break;
        case "restaurant":
            pr.processingRestaurant(response, null);
            break;
        default :
            prepareMessage(response.result.fulfillment.speech);
    }
}

/*
*   Fonction qui prépare le message
*   Recherche de champs à completer
*   Voir la documentation pour le formalisme
*    {{qr:Oui}} {{qr:Non}}
*/
function prepareMessage(response) {
    var messages = [];
    var replie = response;
    var fields = fd.extractFields(replie);
    var quickreplies = extractQuickReplies(fields);
    replie = fd.removeFields(replie);
    if(quickreplies.length > 0) {
        prepareMessageWithQuickReply(replie, quickreplies, messages);
    } else if(replie != undefined ) {
        prepareMessageWithText(replie, messages);
    }
    sendMessages(messages);
}

/*
*   Fonction qui extrait les quick replies
*/
function extractQuickReplies(fields) {
    var quickreplies = [];
    for(var i=0;i<fields.length;i++)
    {
        var json = undefined;
        try {
            json = JSON.parse(fields[i]);
        } catch (err){
        }
        if(json != undefined && json.qr != undefined && json.qr.length > 0) {
            for(var j=0;j<json.qr.length;j++) {
                quickreplies.push(json.qr[j]);
            }
        }
    }
    return quickreplies;
}

/*
*   Fonction qui prépare un message de type text
*/
function prepareMessageWithText(text, messages) {
    var message = {
        type: "text",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text
    };
    messages.push(message);
}

/*
*   Fonction qui prépare un message de type quickreply
*/
function prepareMessageWithQuickReply(text, quickreply, messages) {
    var message = {
        type: "quickreply",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text,
        choices:[]
    }
    if(Array.isArray(quickreply)) {
        for(var i=0;i<quickreply.length;i++) {
            message.choices.push(quickreply[i]);
        }
    } else {
        message.choices.push(quickreply);
    }
    messages.push(message);
}

function askLocation() {
    var message = {
        type: "location",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: "J'ai besoin de votre localisation"
    }
    messages.push(message);
}

/*
*   Fonction qui appelle la fonction d'envoie de message
*/
function sendMessages(messages) {
    if(messages.length > 0) {
        switch(messages[0].channel) {
        case "Facebook":
            facebook.sendMessages(messages);
            break;
        case "Telegram":
            telegram.sendMessages(messages);
            break;
        case "Aslan":
            aslan.sendMessages(messages);
            break;
        default:
            return;
        }
    }
}

function getLastIntent(message) {
    db.getData("conversation", {sessionId: message.senderId}, function(data) {
        if(data.length == 0) {
            console.log("Aucun intent trouvé");
        } else {
            switch(data[0].result.metadata.intentName) {
            case "restaurant":
                apiai.sendMessage(message.senderID, "[localisation:success]", callbackLogicLayer)
                pr.processingRestaurant(message.location);
                break;
            default:
               break;
            }
        }
    });
}

exports.askLocation = askLocation;
exports.receivedMessage = receivedMessage;
exports.prepareMessage = prepareMessage;<commit_msg>Fix bug<commit_after>'use strict';

//const recast = require('./botlogic/recast.js');
const apiai = require('./../botlogic/apiai.js');
const facebook = require('./../channels/facebook.js');
const telegram = require('./../channels/telegram.js');
const aslan = require('./../channels/aslan-messenger.js');
const pr = require('./processing.js');
const fd = require('./field.js');

var messageReceived;

/*
*   Fonction appelée par les channels lorsque l'on reçoit un message
*/
function receivedMessage(message) {
    messageReceived = message;
    if(message.location != undefined) {
        getLastIntent(message);
    } else {
        runLogicLayer(message);
    }
}

/*
*   Fonction qu lance la couche logique avec NLP
*/
function runLogicLayer(message) {
    /*botlogic.defineCallback(callbackLogicLayer);
    if(message.senderID != undefined && message.text != undefined) {
        botlogic.sendMessage(message.text, `session-${message.senderID}`, {});
    }*/
    /*recast.sendMessage(message.text, callbackLogicLayer);*/
    apiai.sendMessage(message.senderID, message.text, callbackLogicLayer)
}

/*
*   Fonction de callback appelée par la couche logique
*/
function callbackLogicLayer(response) {
    console.log("APIAI sended : ", JSON.stringify(response));
    var intent = response.result.metadata.intentName;
    processing(intent, response);
}

/*
*   Fonction qui traite le message en fonction du contexte du message
*   La fonction renvoie la réponse à la channel
*/
function processing(intent, response) {
    switch(intent) {
        case "bonjour" :
            pr.processingGrettings(messageReceived, response);
            break;
        case "heure" :
            pr.processingHour(response);
            break;
        case "fontaine" :
            pr.processingFountain(response);
            break;
        case "habitant":
            pr.processingCitizen(response);
            break;
        case "jour":
            pr.processingDate(response);
            break;
        case "meteo":
            pr.processingWeather(response);
            break;
        case "restaurant":
            pr.processingRestaurant(response, null);
            break;
        default :
            prepareMessage(response.result.fulfillment.speech);
    }
}

/*
*   Fonction qui prépare le message
*   Recherche de champs à completer
*   Voir la documentation pour le formalisme
*    {{qr:Oui}} {{qr:Non}}
*/
function prepareMessage(response) {
    var messages = [];
    var replie = response;
    var fields = fd.extractFields(replie);
    var quickreplies = extractQuickReplies(fields);
    replie = fd.removeFields(replie);
    if(quickreplies.length > 0) {
        prepareMessageWithQuickReply(replie, quickreplies, messages);
    } else if(replie != undefined ) {
        prepareMessageWithText(replie, messages);
    }
    sendMessages(messages);
}

/*
*   Fonction qui extrait les quick replies
*/
function extractQuickReplies(fields) {
    var quickreplies = [];
    for(var i=0;i<fields.length;i++)
    {
        var json = undefined;
        try {
            json = JSON.parse(fields[i]);
        } catch (err){
        }
        if(json != undefined && json.qr != undefined && json.qr.length > 0) {
            for(var j=0;j<json.qr.length;j++) {
                quickreplies.push(json.qr[j]);
            }
        }
    }
    return quickreplies;
}

/*
*   Fonction qui prépare un message de type text
*/
function prepareMessageWithText(text, messages) {
    var message = {
        type: "text",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text
    };
    messages.push(message);
}

/*
*   Fonction qui prépare un message de type quickreply
*/
function prepareMessageWithQuickReply(text, quickreply, messages) {
    var message = {
        type: "quickreply",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text,
        choices:[]
    }
    if(Array.isArray(quickreply)) {
        for(var i=0;i<quickreply.length;i++) {
            message.choices.push(quickreply[i]);
        }
    } else {
        message.choices.push(quickreply);
    }
    messages.push(message);
}

function askLocation() {
    var message = {
        type: "location",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: "J'ai besoin de votre localisation"
    }
    sendMessage([messages.push(message)]);
}

/*
*   Fonction qui appelle la fonction d'envoie de message
*/
function sendMessages(messages) {
    if(messages.length > 0) {
        switch(messages[0].channel) {
        case "Facebook":
            facebook.sendMessages(messages);
            break;
        case "Telegram":
            telegram.sendMessages(messages);
            break;
        case "Aslan":
            aslan.sendMessages(messages);
            break;
        default:
            return;
        }
    }
}

function getLastIntent(message) {
    db.getData("conversation", {sessionId: message.senderId}, function(data) {
        if(data.length == 0) {
            console.log("Aucun intent trouvé");
        } else {
            switch(data[0].result.metadata.intentName) {
            case "restaurant":
                apiai.sendMessage(message.senderID, "[localisation:success]", callbackLogicLayer)
                pr.processingRestaurant(message.location);
                break;
            default:
               break;
            }
        }
    });
}

exports.askLocation = askLocation;
exports.receivedMessage = receivedMessage;
exports.prepareMessage = prepareMessage;<|endoftext|>


<commit_before>'use strict';

//const recast = require('./botlogic/recast.js');
const apiai = require('./../botlogic/apiai.js');
const facebook = require('./../channels/facebook.js');
const telegram = require('./../channels/telegram.js');
const aslan = require('./../channels/aslan-messenger.js');
const pr = require('./processing.js');
const fd = require('./field.js');

var messageReceived;

/*
*   Fonction appelée par les channels lorsque l'on reçoit un message
*/
function receivedMessage(message) {
    messageReceived = message;
    if(message.location != undefined) {
        getLastIntent(message);
    } else {
        runLogicLayer(message);
    }
}

/*
*   Fonction qu lance la couche logique avec NLP
*/
function runLogicLayer(message) {
    /*botlogic.defineCallback(callbackLogicLayer);
    if(message.senderID != undefined && message.text != undefined) {
        botlogic.sendMessage(message.text, `session-${message.senderID}`, {});
    }*/
    /*recast.sendMessage(message.text, callbackLogicLayer);*/
    apiai.sendMessage(message.senderID, message.text, callbackLogicLayer)
}

/*
*   Fonction de callback appelée par la couche logique
*/
function callbackLogicLayer(response) {
    console.log("APIAI sended : ", JSON.stringify(response));
    var intent = response.result.metadata.intentName;
    processing(intent, response);
}

/*
*   Fonction qui traite le message en fonction du contexte du message
*   La fonction renvoie la réponse à la channel
*/
function processing(intent, response) {
    switch(intent) {
        case "bonjour" :
            pr.processingGrettings(messageReceived, response);
            break;
        case "heure" :
            pr.processingHour(response);
            break;
        case "fontaine" :
            pr.processingFountain(response);
            break;
        case "habitant":
            pr.processingCitizen(response);
            break;
        case "jour":
            pr.processingDate(response);
            break;
        case "meteo":
            pr.processingWeather(response);
            break;
        case "restaurant":
            pr.processingRestaurant(response, null);
            break;
        default :
            prepareMessage(response.result.fulfillment.speech);
    }
}

/*
*   Fonction qui prépare le message
*   Recherche de champs à completer
*   Voir la documentation pour le formalisme
*    {{qr:Oui}} {{qr:Non}}
*/
function prepareMessage(response) {
    var messages = [];
    var replie = response;
    var fields = fd.extractFields(replie);
    var quickreplies = extractQuickReplies(fields);
    replie = fd.removeFields(replie);
    if(quickreplies.length > 0) {
        prepareMessageWithQuickReply(replie, quickreplies, messages);
    } else if(replie != undefined ) {
        prepareMessageWithText(replie, messages);
    }
    sendMessages(messages);
}

/*
*   Fonction qui extrait les quick replies
*/
function extractQuickReplies(fields) {
    var quickreplies = [];
    for(var i=0;i<fields.length;i++)
    {
        var json = undefined;
        try {
            json = JSON.parse(fields[i]);
        } catch (err){
        }
        if(json != undefined && json.qr != undefined && json.qr.length > 0) {
            for(var j=0;j<json.qr.length;j++) {
                quickreplies.push(json.qr[j]);
            }
        }
    }
    return quickreplies;
}

/*
*   Fonction qui prépare un message de type text
*/
function prepareMessageWithText(text, messages) {
    var message = {
        type: "text",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text
    };
    messages.push(message);
}

/*
*   Fonction qui prépare un message de type quickreply
*/
function prepareMessageWithQuickReply(text, quickreply, messages) {
    var message = {
        type: "quickreply",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text,
        choices:[]
    }
    if(Array.isArray(quickreply)) {
        for(var i=0;i<quickreply.length;i++) {
            message.choices.push(quickreply[i]);
        }
    } else {
        message.choices.push(quickreply);
    }
    messages.push(message);
}

function askLocation() {
    var message = {
        type: "location",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: "J'ai besoin de votre localisation"
    }
    messages.push(message);
}

/*
*   Fonction qui appelle la fonction d'envoie de message
*/
function sendMessages(messages) {
    if(messages.length > 0) {
        switch(messages[0].channel) {
        case "Facebook":
            facebook.sendMessages(messages);
            break;
        case "Telegram":
            telegram.sendMessages(messages);
            break;
        case "Aslan":
            aslan.sendMessages(messages);
            break;
        default:
            return;
        }
    }
}

function getLastIntent(message) {
    db.getData("conversation", {sessionId: message.senderId}, function(data) {
        if(data.length == 0) {
            console.log("Aucun intent trouvé");
        } else {
            switch(data[0].result.metadata.intentName;) {
            case "restaurant":
                apiai.sendMessage(message.senderID, "[localisation:success]", callbackLogicLayer)
                pr.processingRestaurant(message.location);
                break;
            default:
               break;
            }
        }
    });
}

exports.receivedMessage = receivedMessage;
exports.prepareMessage = prepareMessage;<commit_msg>Fix bug<commit_after>'use strict';

//const recast = require('./botlogic/recast.js');
const apiai = require('./../botlogic/apiai.js');
const facebook = require('./../channels/facebook.js');
const telegram = require('./../channels/telegram.js');
const aslan = require('./../channels/aslan-messenger.js');
const pr = require('./processing.js');
const fd = require('./field.js');

var messageReceived;

/*
*   Fonction appelée par les channels lorsque l'on reçoit un message
*/
function receivedMessage(message) {
    messageReceived = message;
    if(message.location != undefined) {
        getLastIntent(message);
    } else {
        runLogicLayer(message);
    }
}

/*
*   Fonction qu lance la couche logique avec NLP
*/
function runLogicLayer(message) {
    /*botlogic.defineCallback(callbackLogicLayer);
    if(message.senderID != undefined && message.text != undefined) {
        botlogic.sendMessage(message.text, `session-${message.senderID}`, {});
    }*/
    /*recast.sendMessage(message.text, callbackLogicLayer);*/
    apiai.sendMessage(message.senderID, message.text, callbackLogicLayer)
}

/*
*   Fonction de callback appelée par la couche logique
*/
function callbackLogicLayer(response) {
    console.log("APIAI sended : ", JSON.stringify(response));
    var intent = response.result.metadata.intentName;
    processing(intent, response);
}

/*
*   Fonction qui traite le message en fonction du contexte du message
*   La fonction renvoie la réponse à la channel
*/
function processing(intent, response) {
    switch(intent) {
        case "bonjour" :
            pr.processingGrettings(messageReceived, response);
            break;
        case "heure" :
            pr.processingHour(response);
            break;
        case "fontaine" :
            pr.processingFountain(response);
            break;
        case "habitant":
            pr.processingCitizen(response);
            break;
        case "jour":
            pr.processingDate(response);
            break;
        case "meteo":
            pr.processingWeather(response);
            break;
        case "restaurant":
            pr.processingRestaurant(response, null);
            break;
        default :
            prepareMessage(response.result.fulfillment.speech);
    }
}

/*
*   Fonction qui prépare le message
*   Recherche de champs à completer
*   Voir la documentation pour le formalisme
*    {{qr:Oui}} {{qr:Non}}
*/
function prepareMessage(response) {
    var messages = [];
    var replie = response;
    var fields = fd.extractFields(replie);
    var quickreplies = extractQuickReplies(fields);
    replie = fd.removeFields(replie);
    if(quickreplies.length > 0) {
        prepareMessageWithQuickReply(replie, quickreplies, messages);
    } else if(replie != undefined ) {
        prepareMessageWithText(replie, messages);
    }
    sendMessages(messages);
}

/*
*   Fonction qui extrait les quick replies
*/
function extractQuickReplies(fields) {
    var quickreplies = [];
    for(var i=0;i<fields.length;i++)
    {
        var json = undefined;
        try {
            json = JSON.parse(fields[i]);
        } catch (err){
        }
        if(json != undefined && json.qr != undefined && json.qr.length > 0) {
            for(var j=0;j<json.qr.length;j++) {
                quickreplies.push(json.qr[j]);
            }
        }
    }
    return quickreplies;
}

/*
*   Fonction qui prépare un message de type text
*/
function prepareMessageWithText(text, messages) {
    var message = {
        type: "text",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text
    };
    messages.push(message);
}

/*
*   Fonction qui prépare un message de type quickreply
*/
function prepareMessageWithQuickReply(text, quickreply, messages) {
    var message = {
        type: "quickreply",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: text,
        choices:[]
    }
    if(Array.isArray(quickreply)) {
        for(var i=0;i<quickreply.length;i++) {
            message.choices.push(quickreply[i]);
        }
    } else {
        message.choices.push(quickreply);
    }
    messages.push(message);
}

function askLocation() {
    var message = {
        type: "location",
        senderID: messageReceived.senderID,
        channel: messageReceived.channel,
        text: "J'ai besoin de votre localisation"
    }
    messages.push(message);
}

/*
*   Fonction qui appelle la fonction d'envoie de message
*/
function sendMessages(messages) {
    if(messages.length > 0) {
        switch(messages[0].channel) {
        case "Facebook":
            facebook.sendMessages(messages);
            break;
        case "Telegram":
            telegram.sendMessages(messages);
            break;
        case "Aslan":
            aslan.sendMessages(messages);
            break;
        default:
            return;
        }
    }
}

function getLastIntent(message) {
    db.getData("conversation", {sessionId: message.senderId}, function(data) {
        if(data.length == 0) {
            console.log("Aucun intent trouvé");
        } else {
            switch(data[0].result.metadata.intentName) {
            case "restaurant":
                apiai.sendMessage(message.senderID, "[localisation:success]", callbackLogicLayer)
                pr.processingRestaurant(message.location);
                break;
            default:
               break;
            }
        }
    });
}

exports.receivedMessage = receivedMessage;
exports.prepareMessage = prepareMessage;<|endoftext|>


<commit_before>import logger from 'loglevel'

// We faced a bug in babel so that transform-runtime with export * from 'x' generates import statements in transpiled code
// Tracked here : https://github.com/babel/babel/issues/2877
// We tested the workaround given here https://github.com/babel/babel/issues/2877#issuecomment-270700000 with success so far

// FIXME: we don't build vue component anymore, they are processed by webpack in the application template
// export * from './components'

export * from './api'
export * from './store'
export * from './guards'
export * as mixins from './mixins'
export * as hooks from './hooks'

export default function init () {
  // const app = this

  logger.debug('Initializing kalisio core')
}
<commit_msg>Added 'patched' event listener on the users service in order to update the current user<commit_after>import logger from 'loglevel'
import { Store } from './store'

// We faced a bug in babel so that transform-runtime with export * from 'x' generates import statements in transpiled code
// Tracked here : https://github.com/babel/babel/issues/2877
// We tested the workaround given here https://github.com/babel/babel/issues/2877#issuecomment-270700000 with success so far

// FIXME: we don't build vue component anymore, they are processed by webpack in the application template
// export * from './components'

export * from './api'
export * from './store'
export * from './guards'
export * as mixins from './mixins'
export * as hooks from './hooks'

export default function init () {
  const app = this

  // Listen to the 'patched' event on the users
  const users = app.getService('users')
  users.on('patched', user => {
    // Check whether we need to update the current logged user
    if (user._id === this.Store.get('user._id')) {
      Store.set('user', user)
    }
  })

  logger.debug('Initializing kalisio core')
}
<|endoftext|>


<commit_before>/**
 * Module of mixed-in functions shared between node and client code
 */
var isObject = require('./is-object');

/**
 * Expose `RequestBase`.
 */

module.exports = RequestBase;

/**
 * Initialize a new `RequestBase`.
 *
 * @api public
 */

function RequestBase(obj) {
  if (obj) return mixin(obj);
}

/**
 * Mixin the prototype properties.
 *
 * @param {Object} obj
 * @return {Object}
 * @api private
 */

function mixin(obj) {
  for (var key in RequestBase.prototype) {
    obj[key] = RequestBase.prototype[key];
  }
  return obj;
}

/**
 * Clear previous timeout.
 *
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.clearTimeout = function _clearTimeout(){
  clearTimeout(this._timer);
  clearTimeout(this._responseTimeoutTimer);
  delete this._timer;
  delete this._responseTimeoutTimer;
  return this;
};

/**
 * Override default response body parser
 *
 * This function will be called to convert incoming data into request.body
 *
 * @param {Function}
 * @api public
 */

RequestBase.prototype.parse = function parse(fn){
  this._parser = fn;
  return this;
};

/**
 * Set format of binary response body.
 * In browser valid formats are 'blob' and 'arraybuffer',
 * which return Blob and ArrayBuffer, respectively.
 *
 * In Node all values result in Buffer.
 *
 * Examples:
 *
 *      req.get('/')
 *        .responseType('blob')
 *        .end(callback);
 *
 * @param {String} val
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.responseType = function(val){
  this._responseType = val;
  return this;
};

/**
 * Override default request body serializer
 *
 * This function will be called to convert data set via .send or .attach into payload to send
 *
 * @param {Function}
 * @api public
 */

RequestBase.prototype.serialize = function serialize(fn){
  this._serializer = fn;
  return this;
};

/**
 * Set timeouts.
 *
 * - response timeout is time between sending request and receiving the first byte of the response. Includes DNS and connection time.
 * - deadline is the time from start of the request to receiving response body in full. If the deadline is too short large files may not load at all on slow connections.
 *
 * Value of 0 or false means no timeout.
 *
 * @param {Number|Object} ms or {response, read, deadline}
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.timeout = function timeout(options){
  if (!options || 'object' !== typeof options) {
    this._timeout = options;
    this._responseTimeout = 0;
    return this;
  }

  if ('undefined' !== typeof options.deadline) {
    this._timeout = options.deadline;
  }
  if ('undefined' !== typeof options.response) {
    this._responseTimeout = options.response;
  }
  return this;
};

/**
 * Set number of retry attempts on error.
 *
 * Failed requests will be retried 'count' times if timeout or err.code >= 500.
 *
 * @param {Number} count
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.retry = function retry(count){
  // Default to 1 if no count passed or true
  if (!('0' in arguments) || count === true) count = 1;
  if (count == null || count <= 0) count = 0;
  this._maxRetries = count;
  this._retries = 0;
  return this;
};

/**
 * Retry request
 *
 * @return {Request} for chaining
 * @api private
 */

RequestBase.prototype._retry = function() {
  this.clearTimeout();

  // node
  if (this.req) {
    this.req = null;
    this.req = this.request();
  }

  this._aborted = false;
  this.timedout = false;

  return this._end();
};

/**
 * Promise support
 *
 * @param {Function} resolve
 * @param {Function} [reject]
 * @return {Request}
 */

RequestBase.prototype.then = function then(resolve, reject) {
  if (!this._fullfilledPromise) {
    var self = this;
    if (this._endCalled) {
      console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises");
    }
    this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
      self.end(function(err, res){
        if (err) innerReject(err); else innerResolve(res);
      });
    });
  }
  return this._fullfilledPromise.then(resolve, reject);
}

RequestBase.prototype.catch = function(cb) {
  return this.then(undefined, cb);
};

/**
 * Allow for extension
 */

RequestBase.prototype.use = function use(fn) {
  fn(this);
  return this;
}

RequestBase.prototype.ok = function(cb) {
  if ('function' !== typeof cb) throw Error("Callback required");
  this._okCallback = cb;
  return this;
};

RequestBase.prototype._isResponseOK = function(res) {
  if (!res) {
    return false;
  }

  if (this._okCallback) {
    return this._okCallback(res);
  }

  return res.status >= 200 && res.status < 300;
};

/**
 * Get request header `field`.
 * Case-insensitive.
 *
 * @param {String} field
 * @return {String}
 * @api public
 */

RequestBase.prototype.get = function(field){
  return this._header[field.toLowerCase()];
};

/**
 * Get case-insensitive header `field` value.
 * This is a deprecated internal API. Use `.get(field)` instead.
 *
 * (getHeader is no longer used internally by the superagent code base)
 *
 * @param {String} field
 * @return {String}
 * @api private
 * @deprecated
 */

RequestBase.prototype.getHeader = RequestBase.prototype.get;

/**
 * Set header `field` to `val`, or multiple fields with one object.
 * Case-insensitive.
 *
 * Examples:
 *
 *      req.get('/')
 *        .set('Accept', 'application/json')
 *        .set('X-API-Key', 'foobar')
 *        .end(callback);
 *
 *      req.get('/')
 *        .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
 *        .end(callback);
 *
 * @param {String|Object} field
 * @param {String} val
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.set = function(field, val){
  if (isObject(field)) {
    for (var key in field) {
      this.set(key, field[key]);
    }
    return this;
  }
  this._header[field.toLowerCase()] = val;
  this.header[field] = val;
  return this;
};

/**
 * Remove header `field`.
 * Case-insensitive.
 *
 * Example:
 *
 *      req.get('/')
 *        .unset('User-Agent')
 *        .end(callback);
 *
 * @param {String} field
 */
RequestBase.prototype.unset = function(field){
  delete this._header[field.toLowerCase()];
  delete this.header[field];
  return this;
};

/**
 * Write the field `name` and `val`, or multiple fields with one object
 * for "multipart/form-data" request bodies.
 *
 * ``` js
 * request.post('/upload')
 *   .field('foo', 'bar')
 *   .end(callback);
 *
 * request.post('/upload')
 *   .field({ foo: 'bar', baz: 'qux' })
 *   .end(callback);
 * ```
 *
 * @param {String|Object} name
 * @param {String|Blob|File|Buffer|fs.ReadStream} val
 * @return {Request} for chaining
 * @api public
 */
RequestBase.prototype.field = function(name, val) {

  // name should be either a string or an object.
  if (null === name ||  undefined === name) {
    throw new Error('.field(name, val) name can not be empty');
  }

  if (this._data) {
    console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
  }

  if (isObject(name)) {
    for (var key in name) {
      this.field(key, name[key]);
    }
    return this;
  }

  if (Array.isArray(val)) {
    for (var i in val) {
      this.field(name, val[i]);
    }
    return this;
  }

  // val should be defined now
  if (null === val || undefined === val) {
    throw new Error('.field(name, val) val can not be empty');
  }
  if ('boolean' === typeof val) {
    val = '' + val;
  }
  this._getFormData().append(name, val);
  return this;
};

/**
 * Abort the request, and clear potential timeout.
 *
 * @return {Request}
 * @api public
 */
RequestBase.prototype.abort = function(){
  if (this._aborted) {
    return this;
  }
  this._aborted = true;
  this.xhr && this.xhr.abort(); // browser
  this.req && this.req.abort(); // node
  this.clearTimeout();
  this.emit('abort');
  return this;
};

/**
 * Enable transmission of cookies with x-domain requests.
 *
 * Note that for this to work the origin must not be
 * using "Access-Control-Allow-Origin" with a wildcard,
 * and also must set "Access-Control-Allow-Credentials"
 * to "true".
 *
 * @api public
 */

RequestBase.prototype.withCredentials = function(){
  // This is browser-only functionality. Node side is no-op.
  this._withCredentials = true;
  return this;
};

/**
 * Set the max redirects to `n`. Does noting in browser XHR implementation.
 *
 * @param {Number} n
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.redirects = function(n){
  this._maxRedirects = n;
  return this;
};

/**
 * Convert to a plain javascript object (not JSON string) of scalar properties.
 * Note as this method is designed to return a useful non-this value,
 * it cannot be chained.
 *
 * @return {Object} describing method, url, and data of this request
 * @api public
 */

RequestBase.prototype.toJSON = function(){
  return {
    method: this.method,
    url: this.url,
    data: this._data,
    headers: this._header
  };
};

/**
 * Send `data` as the request body, defaulting the `.type()` to "json" when
 * an object is given.
 *
 * Examples:
 *
 *       // manual json
 *       request.post('/user')
 *         .type('json')
 *         .send('{"name":"tj"}')
 *         .end(callback)
 *
 *       // auto json
 *       request.post('/user')
 *         .send({ name: 'tj' })
 *         .end(callback)
 *
 *       // manual x-www-form-urlencoded
 *       request.post('/user')
 *         .type('form')
 *         .send('name=tj')
 *         .end(callback)
 *
 *       // auto x-www-form-urlencoded
 *       request.post('/user')
 *         .type('form')
 *         .send({ name: 'tj' })
 *         .end(callback)
 *
 *       // defaults to x-www-form-urlencoded
 *      request.post('/user')
 *        .send('name=tobi')
 *        .send('species=ferret')
 *        .end(callback)
 *
 * @param {String|Object} data
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.send = function(data){
  var isObj = isObject(data);
  var type = this._header['content-type'];

  if (this._formData) {
    console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
  }

  if (isObj && !this._data) {
    if (Array.isArray(data)) {
      this._data = [];
    } else if (!this._isHost(data)) {
      this._data = {};
    }
  } else if (data && this._data && this._isHost(this._data)) {
    throw Error("Can't merge these send calls");
  }

  // merge
  if (isObj && isObject(this._data)) {
    for (var key in data) {
      this._data[key] = data[key];
    }
  } else if ('string' == typeof data) {
    // default to x-www-form-urlencoded
    if (!type) this.type('form');
    type = this._header['content-type'];
    if ('application/x-www-form-urlencoded' == type) {
      this._data = this._data
        ? this._data + '&' + data
        : data;
    } else {
      this._data = (this._data || '') + data;
    }
  } else {
    this._data = data;
  }

  if (!isObj || this._isHost(data)) {
    return this;
  }

  // default to json
  if (!type) this.type('json');
  return this;
};

/**
 * Sort `querystring` by the sort function
 *
 *
 * Examples:
 *
 *       // default order
 *       request.get('/user')
 *         .query('name=Nick')
 *         .query('search=Manny')
 *         .sortQuery()
 *         .end(callback)
 *
 *       // customized sort function
 *       request.get('/user')
 *         .query('name=Nick')
 *         .query('search=Manny')
 *         .sortQuery(function(a, b){
 *           return a.length - b.length;
 *         })
 *         .end(callback)
 *
 *
 * @param {Function} sort
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.sortQuery = function(sort) {
  // _sort default to true but otherwise can be a function or boolean
  this._sort = typeof sort === 'undefined' ? true : sort;
  return this;
};

/**
 * Invoke callback with timeout error.
 *
 * @api private
 */

RequestBase.prototype._timeoutError = function(reason, timeout){
  if (this._aborted) {
    return;
  }
  var err = new Error(reason + timeout + 'ms exceeded');
  err.timeout = timeout;
  err.code = 'ECONNABORTED';
  this.timedout = true;
  this.abort();
  this.callback(err);
};

RequestBase.prototype._setTimeouts = function() {
  var self = this;

  // deadline
  if (this._timeout && !this._timer) {
    this._timer = setTimeout(function(){
      self._timeoutError('Timeout of ', self._timeout);
    }, this._timeout);
  }
  // response timeout
  if (this._responseTimeout && !this._responseTimeoutTimer) {
    this._responseTimeoutTimer = setTimeout(function(){
      self._timeoutError('Response timeout of ', self._responseTimeout);
    }, this._responseTimeout);
  }
}
<commit_msg>Simplify check<commit_after>/**
 * Module of mixed-in functions shared between node and client code
 */
var isObject = require('./is-object');

/**
 * Expose `RequestBase`.
 */

module.exports = RequestBase;

/**
 * Initialize a new `RequestBase`.
 *
 * @api public
 */

function RequestBase(obj) {
  if (obj) return mixin(obj);
}

/**
 * Mixin the prototype properties.
 *
 * @param {Object} obj
 * @return {Object}
 * @api private
 */

function mixin(obj) {
  for (var key in RequestBase.prototype) {
    obj[key] = RequestBase.prototype[key];
  }
  return obj;
}

/**
 * Clear previous timeout.
 *
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.clearTimeout = function _clearTimeout(){
  clearTimeout(this._timer);
  clearTimeout(this._responseTimeoutTimer);
  delete this._timer;
  delete this._responseTimeoutTimer;
  return this;
};

/**
 * Override default response body parser
 *
 * This function will be called to convert incoming data into request.body
 *
 * @param {Function}
 * @api public
 */

RequestBase.prototype.parse = function parse(fn){
  this._parser = fn;
  return this;
};

/**
 * Set format of binary response body.
 * In browser valid formats are 'blob' and 'arraybuffer',
 * which return Blob and ArrayBuffer, respectively.
 *
 * In Node all values result in Buffer.
 *
 * Examples:
 *
 *      req.get('/')
 *        .responseType('blob')
 *        .end(callback);
 *
 * @param {String} val
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.responseType = function(val){
  this._responseType = val;
  return this;
};

/**
 * Override default request body serializer
 *
 * This function will be called to convert data set via .send or .attach into payload to send
 *
 * @param {Function}
 * @api public
 */

RequestBase.prototype.serialize = function serialize(fn){
  this._serializer = fn;
  return this;
};

/**
 * Set timeouts.
 *
 * - response timeout is time between sending request and receiving the first byte of the response. Includes DNS and connection time.
 * - deadline is the time from start of the request to receiving response body in full. If the deadline is too short large files may not load at all on slow connections.
 *
 * Value of 0 or false means no timeout.
 *
 * @param {Number|Object} ms or {response, read, deadline}
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.timeout = function timeout(options){
  if (!options || 'object' !== typeof options) {
    this._timeout = options;
    this._responseTimeout = 0;
    return this;
  }

  if ('undefined' !== typeof options.deadline) {
    this._timeout = options.deadline;
  }
  if ('undefined' !== typeof options.response) {
    this._responseTimeout = options.response;
  }
  return this;
};

/**
 * Set number of retry attempts on error.
 *
 * Failed requests will be retried 'count' times if timeout or err.code >= 500.
 *
 * @param {Number} count
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.retry = function retry(count){
  // Default to 1 if no count passed or true
  if (arguments.length === 0 || count === true) count = 1;
  if (count <= 0) count = 0;
  this._maxRetries = count;
  this._retries = 0;
  return this;
};

/**
 * Retry request
 *
 * @return {Request} for chaining
 * @api private
 */

RequestBase.prototype._retry = function() {
  this.clearTimeout();

  // node
  if (this.req) {
    this.req = null;
    this.req = this.request();
  }

  this._aborted = false;
  this.timedout = false;

  return this._end();
};

/**
 * Promise support
 *
 * @param {Function} resolve
 * @param {Function} [reject]
 * @return {Request}
 */

RequestBase.prototype.then = function then(resolve, reject) {
  if (!this._fullfilledPromise) {
    var self = this;
    if (this._endCalled) {
      console.warn("Warning: superagent request was sent twice, because both .end() and .then() were called. Never call .end() if you use promises");
    }
    this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
      self.end(function(err, res){
        if (err) innerReject(err); else innerResolve(res);
      });
    });
  }
  return this._fullfilledPromise.then(resolve, reject);
}

RequestBase.prototype.catch = function(cb) {
  return this.then(undefined, cb);
};

/**
 * Allow for extension
 */

RequestBase.prototype.use = function use(fn) {
  fn(this);
  return this;
}

RequestBase.prototype.ok = function(cb) {
  if ('function' !== typeof cb) throw Error("Callback required");
  this._okCallback = cb;
  return this;
};

RequestBase.prototype._isResponseOK = function(res) {
  if (!res) {
    return false;
  }

  if (this._okCallback) {
    return this._okCallback(res);
  }

  return res.status >= 200 && res.status < 300;
};

/**
 * Get request header `field`.
 * Case-insensitive.
 *
 * @param {String} field
 * @return {String}
 * @api public
 */

RequestBase.prototype.get = function(field){
  return this._header[field.toLowerCase()];
};

/**
 * Get case-insensitive header `field` value.
 * This is a deprecated internal API. Use `.get(field)` instead.
 *
 * (getHeader is no longer used internally by the superagent code base)
 *
 * @param {String} field
 * @return {String}
 * @api private
 * @deprecated
 */

RequestBase.prototype.getHeader = RequestBase.prototype.get;

/**
 * Set header `field` to `val`, or multiple fields with one object.
 * Case-insensitive.
 *
 * Examples:
 *
 *      req.get('/')
 *        .set('Accept', 'application/json')
 *        .set('X-API-Key', 'foobar')
 *        .end(callback);
 *
 *      req.get('/')
 *        .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })
 *        .end(callback);
 *
 * @param {String|Object} field
 * @param {String} val
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.set = function(field, val){
  if (isObject(field)) {
    for (var key in field) {
      this.set(key, field[key]);
    }
    return this;
  }
  this._header[field.toLowerCase()] = val;
  this.header[field] = val;
  return this;
};

/**
 * Remove header `field`.
 * Case-insensitive.
 *
 * Example:
 *
 *      req.get('/')
 *        .unset('User-Agent')
 *        .end(callback);
 *
 * @param {String} field
 */
RequestBase.prototype.unset = function(field){
  delete this._header[field.toLowerCase()];
  delete this.header[field];
  return this;
};

/**
 * Write the field `name` and `val`, or multiple fields with one object
 * for "multipart/form-data" request bodies.
 *
 * ``` js
 * request.post('/upload')
 *   .field('foo', 'bar')
 *   .end(callback);
 *
 * request.post('/upload')
 *   .field({ foo: 'bar', baz: 'qux' })
 *   .end(callback);
 * ```
 *
 * @param {String|Object} name
 * @param {String|Blob|File|Buffer|fs.ReadStream} val
 * @return {Request} for chaining
 * @api public
 */
RequestBase.prototype.field = function(name, val) {

  // name should be either a string or an object.
  if (null === name ||  undefined === name) {
    throw new Error('.field(name, val) name can not be empty');
  }

  if (this._data) {
    console.error(".field() can't be used if .send() is used. Please use only .send() or only .field() & .attach()");
  }

  if (isObject(name)) {
    for (var key in name) {
      this.field(key, name[key]);
    }
    return this;
  }

  if (Array.isArray(val)) {
    for (var i in val) {
      this.field(name, val[i]);
    }
    return this;
  }

  // val should be defined now
  if (null === val || undefined === val) {
    throw new Error('.field(name, val) val can not be empty');
  }
  if ('boolean' === typeof val) {
    val = '' + val;
  }
  this._getFormData().append(name, val);
  return this;
};

/**
 * Abort the request, and clear potential timeout.
 *
 * @return {Request}
 * @api public
 */
RequestBase.prototype.abort = function(){
  if (this._aborted) {
    return this;
  }
  this._aborted = true;
  this.xhr && this.xhr.abort(); // browser
  this.req && this.req.abort(); // node
  this.clearTimeout();
  this.emit('abort');
  return this;
};

/**
 * Enable transmission of cookies with x-domain requests.
 *
 * Note that for this to work the origin must not be
 * using "Access-Control-Allow-Origin" with a wildcard,
 * and also must set "Access-Control-Allow-Credentials"
 * to "true".
 *
 * @api public
 */

RequestBase.prototype.withCredentials = function(){
  // This is browser-only functionality. Node side is no-op.
  this._withCredentials = true;
  return this;
};

/**
 * Set the max redirects to `n`. Does noting in browser XHR implementation.
 *
 * @param {Number} n
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.redirects = function(n){
  this._maxRedirects = n;
  return this;
};

/**
 * Convert to a plain javascript object (not JSON string) of scalar properties.
 * Note as this method is designed to return a useful non-this value,
 * it cannot be chained.
 *
 * @return {Object} describing method, url, and data of this request
 * @api public
 */

RequestBase.prototype.toJSON = function(){
  return {
    method: this.method,
    url: this.url,
    data: this._data,
    headers: this._header
  };
};

/**
 * Send `data` as the request body, defaulting the `.type()` to "json" when
 * an object is given.
 *
 * Examples:
 *
 *       // manual json
 *       request.post('/user')
 *         .type('json')
 *         .send('{"name":"tj"}')
 *         .end(callback)
 *
 *       // auto json
 *       request.post('/user')
 *         .send({ name: 'tj' })
 *         .end(callback)
 *
 *       // manual x-www-form-urlencoded
 *       request.post('/user')
 *         .type('form')
 *         .send('name=tj')
 *         .end(callback)
 *
 *       // auto x-www-form-urlencoded
 *       request.post('/user')
 *         .type('form')
 *         .send({ name: 'tj' })
 *         .end(callback)
 *
 *       // defaults to x-www-form-urlencoded
 *      request.post('/user')
 *        .send('name=tobi')
 *        .send('species=ferret')
 *        .end(callback)
 *
 * @param {String|Object} data
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.send = function(data){
  var isObj = isObject(data);
  var type = this._header['content-type'];

  if (this._formData) {
    console.error(".send() can't be used if .attach() or .field() is used. Please use only .send() or only .field() & .attach()");
  }

  if (isObj && !this._data) {
    if (Array.isArray(data)) {
      this._data = [];
    } else if (!this._isHost(data)) {
      this._data = {};
    }
  } else if (data && this._data && this._isHost(this._data)) {
    throw Error("Can't merge these send calls");
  }

  // merge
  if (isObj && isObject(this._data)) {
    for (var key in data) {
      this._data[key] = data[key];
    }
  } else if ('string' == typeof data) {
    // default to x-www-form-urlencoded
    if (!type) this.type('form');
    type = this._header['content-type'];
    if ('application/x-www-form-urlencoded' == type) {
      this._data = this._data
        ? this._data + '&' + data
        : data;
    } else {
      this._data = (this._data || '') + data;
    }
  } else {
    this._data = data;
  }

  if (!isObj || this._isHost(data)) {
    return this;
  }

  // default to json
  if (!type) this.type('json');
  return this;
};

/**
 * Sort `querystring` by the sort function
 *
 *
 * Examples:
 *
 *       // default order
 *       request.get('/user')
 *         .query('name=Nick')
 *         .query('search=Manny')
 *         .sortQuery()
 *         .end(callback)
 *
 *       // customized sort function
 *       request.get('/user')
 *         .query('name=Nick')
 *         .query('search=Manny')
 *         .sortQuery(function(a, b){
 *           return a.length - b.length;
 *         })
 *         .end(callback)
 *
 *
 * @param {Function} sort
 * @return {Request} for chaining
 * @api public
 */

RequestBase.prototype.sortQuery = function(sort) {
  // _sort default to true but otherwise can be a function or boolean
  this._sort = typeof sort === 'undefined' ? true : sort;
  return this;
};

/**
 * Invoke callback with timeout error.
 *
 * @api private
 */

RequestBase.prototype._timeoutError = function(reason, timeout){
  if (this._aborted) {
    return;
  }
  var err = new Error(reason + timeout + 'ms exceeded');
  err.timeout = timeout;
  err.code = 'ECONNABORTED';
  this.timedout = true;
  this.abort();
  this.callback(err);
};

RequestBase.prototype._setTimeouts = function() {
  var self = this;

  // deadline
  if (this._timeout && !this._timer) {
    this._timer = setTimeout(function(){
      self._timeoutError('Timeout of ', self._timeout);
    }, this._timeout);
  }
  // response timeout
  if (this._responseTimeout && !this._responseTimeoutTimer) {
    this._responseTimeoutTimer = setTimeout(function(){
      self._timeoutError('Response timeout of ', self._responseTimeout);
    }, this._responseTimeout);
  }
}
<|endoftext|>


<commit_before>//˳㷨<commit_msg>Initial commit<commit_after>//顺序搜索算法<|endoftext|>


<commit_before>/**
 * We.js route alias feature
 */
var we ;

var alias = {
  // alias cache
  cache: {},

  /**
   * Initialize we.js alias feature
   *
   * @param  {O}   we
   * @param  {Object}   we we.js
   * @param  {Function} cb callback
   */
  initialize: function initialize(w, cb) {
    we = w;
    alias.loadAndCacheAllALias().spread(function (results){
      for (var i = results.length - 1; i >= 0; i--) {
        alias.cache[results[i].target] = results[i];
      }

      cb();
    }).catch(cb);
  },

  /**
   * Load all alias in memory for use with sync methods
   *
   * @param  {Object}   we we.js
   * @param  {Function} cb callback
   * @return {Object} Sequelize query promisse
   */
  loadAndCacheAllALias: function loadAndCacheAllALias() {
    var we = require('../index.js');
    return we.db.defaultConnection.query('SELECT * FROM urlAlias');
  },

  /**
   * http handler to use in http.createServer
   */
  httpHandler: function httpHandler(req, res) {
    var we = require('../index.js');
    var self = this;

    // is a a alias for current url
    // save old url
    req.urlBeforeAlias = req.url;

    // only works with GET requests
    if (req.method != 'GET') return we.express.bind(this)(req, res);

    // skip alias
    for (var i = we.config.router.alias.excludePaths.length - 1; i >= 0; i--) {
     if (req.url.indexOf(we.config.router.alias.excludePaths[i]) === 0){
       return we.express.bind(this)(req, res);
     }
    }

    var urlParts = req.url.split(/[?#]/);
    var path = urlParts[0];

    if (!path) return we.express.bind(this)(req, res);

    var query = '';
    if (urlParts[1]) query =  '?' + urlParts[1];

    var cacheUrlAlias = we.router.alias.cache[path];
    // current path is alias and are cached
    if (cacheUrlAlias) {
      // set alias attrs for use in html redirect
      req.haveAlias = cacheUrlAlias;
      req.aliasQuery = query;
      return we.express.bind(self)(req, res);
    }

    // then check if current path have alias or is an uncached alias
    we.db.models.urlAlias.findOne({
      where: {
        $or: [ { alias: path }, { target: path } ]
      }
    }).then(function (urlAlias) {
      if (urlAlias) {
        // is alias and have a real url
        if (urlAlias.alias == path) {
          // save the url alias record
          req.urlAlias = urlAlias;

          req.url = urlAlias.target;

          // update alias for this patch if need
          if (we.router.alias.cache[req.url].alias != path)
            we.router.alias.cache[req.url] = urlAlias;

          if (query) req.url += '?' + query;

          we.log.verbose('ulrAlias set for: ' + path + ' to: '+ req.url);
          // save alias in cache
          if (!alias.cache[path]) alias.cache[path] = urlAlias;
          we.express.bind(this)(req, res);
        } else {
        // is target and have an alias

          // save it in cache
          we.router.alias.cache[path] = urlAlias;
          // set alias attrs for use in html redirect
          req.haveAlias = urlAlias;
          req.aliasQuery = query;
          return we.express.bind(self)(req, res);
        }
      } else {
        we.log.verbose('ulrAlias not found for:', path);
        // slug not found then continue with default express middlewares
        we.express.bind(self)(req, res);
      }
    }).catch(function errorInSlugHandler(err){
      we.log.error(err);
      res.status(500).end();
    });
  },

  /**
   * Check if path have a alias
   *
   * @param  {String} path
   * @return {String} Alias or null
   */
  forPath: function forPath(path) {
    if (alias.cache[path]) {
      return alias.cache[path].alias;
    } else {
      return null;
    }
  },

  /**
   * Return the alias if avaible or path
   *
   * @param  {String} path
   * @return {String} Alias or the path
   */
  resolvePath: function resolvePath(path) {
    if (alias.cache[path]) {
      return alias.cache[path].alias;
    } else {
      return path;
    }
  },

  /**
   * Check if a sequelize model class have alias
   *
   * @param  {Object} Model Sequelize model class
   * @return {Boolean}
   */
  modelHaveUrlAlias: function modelHaveUrlAlias(Model) {
    return Boolean (
      Model.options &&
      (Model.options.enableAlias !== false) &&
      Model.options.classMethods &&
      Model.options.classMethods.urlAlias
    );
  },

  // Model hook functions
  //

  /**
   * Code to run after create a record with alias
   *
   * @param  {Object}   record Sequelize record
   * @param  {Object}   opts   sequelize options
   * @param  {Function} done   callback
   */
  afterCreatedRecord: function afterCreatedRecord(record, opts, done) {
    if (!we) return done();

    var aliasObj = opts.model.options.classMethods.urlAlias(record);

    if (!aliasObj) return done();

    var newAlias = record.setAlias;
    if (newAlias) {
      aliasObj.alias = record.setAlias;
    }

    if (aliasObj.alias[0] !== '/')  aliasObj.alias = '/'+aliasObj.alias;

    we.db.models.urlAlias.create(aliasObj)
    .then(function (alS) {
      we.log.verbose('New url alias:', alS.id);
      done();
    }).catch(function (err){
      we.log.error('Error in generate url alias:', err);
      done();
    });
  },

  /**
   * Code to run after update a record with alias
   *
   * DISABLED by default
   *
   * @param  {Object}   record Sequelize record
   * @param  {Object}   opts   sequelize options
   * @param  {Function} done   callback
   */
  afterUpdatedRecord: function afterUpdatedRecord(record, opts, done) {
    if (!we) return done();

    var newAlias = record.setAlias;
    // only update if set setAlias body field
    if (!newAlias) return done();

    // aff stash if dont starts with slash
    if (newAlias[0] !== '/') record.setAlias = '/'+newAlias

    var aliasObj = {
      alias: record.setAlias,
      target: record.getUrlPath()
    };

    if (alias.cache[aliasObj.target]) {
      // alias found then update
      if (alias.cache[aliasObj.target].alias == aliasObj.alias) {
        // salved alias is same as new then do nothing
        return done();
      }

      we.db.models.urlAlias.findById(alias.cache[aliasObj.target].id)
      .then(function(a){
        a.updateAttributes(aliasObj).then(function(){
          done();
        }).catch(function (err){
          we.log.error('Error in updateAttributes url alias:', err);
          done();
        });
      }).catch(function (err) {
        we.log.error('Error in update url alias:', err);
        done();
      });
    } else {
      // this model dont have a alias, then create one
      we.db.models.urlAlias.create(aliasObj)
      .then(function (alS) {
        we.log.verbose('New url alias:', alS.id);
        done();
      }).catch(function (err){
        we.log.error('Error in generate url alias for:', err);
        done();
      });
    }
  },

  /**
   * Code to run after delete a record with alias
   *
   * @param  {Object}   record Sequelize record
   * @param  {Object}   opts   sequelize options
   * @param  {Function} done   callback
   */
  afterDeleteRecord: function afterDeleteRecord(record, opts, done) {
    if (!we || !record.getUrlPath) return done();

    var p = record.getUrlPath();

    if (!p) return done();

    we.db.models.urlAlias.destroy({
      individualHooks: true,
      where: { target: p }
    }).then(function (count) {
      we.log.verbose(count+' url alias deleted for path: '+p);
      done();
    }).catch(function (err) {
      we.log.error('Error in delete url alias:', err);
      done();
    });
  }
}

module.exports = alias;<commit_msg>update url alias cache reload logic<commit_after>/**
 * We.js route alias feature
 *
 * alias = temporary url or clean url
 * target = url permanent
 */
var we ;

var alias = {
  // alias cache
  cache: {},

  /**
   * Initialize we.js alias feature
   *
   * @param  {O}   we
   * @param  {Object}   we we.js
   * @param  {Function} cb callback
   */
  initialize: function initialize(w, cb) {
    we = w;
    alias.loadAndCacheAllALias().spread(function (results){
      for (var i = results.length - 1; i >= 0; i--) {
        alias.cache[results[i].target] = results[i];
      }

      cb();
    }).catch(cb);
  },

  /**
   * Load all alias in memory for use with sync methods
   *
   * @param  {Object}   we we.js
   * @param  {Function} cb callback
   * @return {Object} Sequelize query promisse
   */
  loadAndCacheAllALias: function loadAndCacheAllALias() {
    var we = require('../index.js');
    return we.db.defaultConnection.query('SELECT * FROM urlAlias');
  },

  /**
   * http handler to use in http.createServer
   */
  httpHandler: function httpHandler(req, res) {
    var we = require('../index.js');
    var self = this;

    // is a a alias for current url
    // save old url
    req.urlBeforeAlias = req.url;

    // only works with GET requests
    if (req.method != 'GET') return we.express.bind(this)(req, res);

    // skip alias
    for (var i = we.config.router.alias.excludePaths.length - 1; i >= 0; i--) {
     if (req.url.indexOf(we.config.router.alias.excludePaths[i]) === 0){
       return we.express.bind(this)(req, res);
     }
    }

    var urlParts = req.url.split(/[?#]/);
    var path = urlParts[0];

    if (!path) return we.express.bind(this)(req, res);

    var query = '';
    if (urlParts[1]) query =  '?' + urlParts[1];

    var cacheUrlAlias = we.router.alias.cache[path];
    // current path is alias and are cached
    if (cacheUrlAlias) {
      // set alias attrs for use in html redirect
      req.haveAlias = cacheUrlAlias;
      req.aliasQuery = query;
      return we.express.bind(self)(req, res);
    }

    // then check if current path have alias or is an uncached alias
    we.db.models.urlAlias.findOne({
      where: {
        $or: [ { alias: path }, { target: path } ]
      }
    }).then(function (urlAlias) {
      if (urlAlias) {
        // is alias and have a target url
        if (urlAlias.alias == path) {
          // save the url alias record
          req.urlAlias = urlAlias;

          req.url = urlAlias.target;

          // update alias for this patch if need
          if (we.router.alias.cache[req.url].alias != path)
            we.router.alias.cache[req.url] = urlAlias;

          if (query) req.url += '?' + query;

          we.log.verbose('ulrAlias set for: ' + path + ' to: '+ req.url);

          // save alias in cache
          if (!alias.cache[urlAlias.target])
            alias.cache[urlAlias.target] = urlAlias;

          we.express.bind(this)(req, res);
        } else {
        // is target and have an alias but dont are in cache

          // save it in cache
          we.router.alias.cache[path] = urlAlias;
          // set alias attrs for use in html redirect
          req.haveAlias = urlAlias;
          req.aliasQuery = query;
          return we.express.bind(self)(req, res);
        }
      } else {
        we.log.verbose('ulrAlias not found for:', path);
        // slug not found then continue with default express middlewares
        we.express.bind(self)(req, res);
      }
    }).catch(function errorInSlugHandler(err){
      we.log.error(err);
      res.status(500).end();
    });
  },

  /**
   * Check if path have a alias
   *
   * @param  {String} path
   * @return {String} Alias or null
   */
  forPath: function forPath(path) {
    if (alias.cache[path]) {
      return alias.cache[path].alias;
    } else {
      return null;
    }
  },

  /**
   * Return the alias if avaible or path
   *
   * @param  {String} path
   * @return {String} Alias or the path
   */
  resolvePath: function resolvePath(path) {
    if (alias.cache[path]) {
      return alias.cache[path].alias;
    } else {
      return path;
    }
  },

  /**
   * Check if a sequelize model class have alias
   *
   * @param  {Object} Model Sequelize model class
   * @return {Boolean}
   */
  modelHaveUrlAlias: function modelHaveUrlAlias(Model) {
    return Boolean (
      Model.options &&
      (Model.options.enableAlias !== false) &&
      Model.options.classMethods &&
      Model.options.classMethods.urlAlias
    );
  },

  // Model hook functions
  //

  /**
   * Code to run after create a record with alias
   *
   * @param  {Object}   record Sequelize record
   * @param  {Object}   opts   sequelize options
   * @param  {Function} done   callback
   */
  afterCreatedRecord: function afterCreatedRecord(record, opts, done) {
    if (!we) return done();

    var aliasObj = opts.model.options.classMethods.urlAlias(record);

    if (!aliasObj) return done();

    var newAlias = record.setAlias;
    if (newAlias) {
      aliasObj.alias = record.setAlias;
    }

    if (aliasObj.alias[0] !== '/')  aliasObj.alias = '/'+aliasObj.alias;

    we.db.models.urlAlias.create(aliasObj)
    .then(function (alS) {
      we.log.verbose('New url alias:', alS.id);
      done();
    }).catch(function (err){
      we.log.error('Error in generate url alias:', err);
      done();
    });
  },

  /**
   * Code to run after update a record with alias
   *
   * DISABLED by default
   *
   * @param  {Object}   record Sequelize record
   * @param  {Object}   opts   sequelize options
   * @param  {Function} done   callback
   */
  afterUpdatedRecord: function afterUpdatedRecord(record, opts, done) {
    if (!we) return done();

    var newAlias = record.setAlias;
    // only update if set setAlias body field
    if (!newAlias) return done();

    // aff stash if dont starts with slash
    if (newAlias[0] !== '/') record.setAlias = '/'+newAlias

    var aliasObj = {
      alias: record.setAlias,
      target: record.getUrlPath()
    };

    if (alias.cache[aliasObj.target]) {
      // alias found then update
      if (alias.cache[aliasObj.target].alias == aliasObj.alias) {
        // salved alias is same as new then do nothing
        return done();
      }

      we.db.models.urlAlias.findById(alias.cache[aliasObj.target].id)
      .then(function(a){
        a.updateAttributes(aliasObj).then(function(){
          done();
        }).catch(function (err){
          we.log.error('Error in updateAttributes url alias:', err);
          done();
        });
      }).catch(function (err) {
        we.log.error('Error in update url alias:', err);
        done();
      });
    } else {
      // this model dont have a alias, then create one
      we.db.models.urlAlias.create(aliasObj)
      .then(function (alS) {
        we.log.verbose('New url alias:', alS.id);
        done();
      }).catch(function (err){
        we.log.error('Error in generate url alias for:', err);
        done();
      });
    }
  },

  /**
   * Code to run after delete a record with alias
   *
   * @param  {Object}   record Sequelize record
   * @param  {Object}   opts   sequelize options
   * @param  {Function} done   callback
   */
  afterDeleteRecord: function afterDeleteRecord(record, opts, done) {
    if (!we || !record.getUrlPath) return done();

    var p = record.getUrlPath();

    if (!p) return done();

    we.db.models.urlAlias.destroy({
      individualHooks: true,
      where: { target: p }
    }).then(function (count) {
      we.log.verbose(count+' url alias deleted for path: '+p);
      done();
    }).catch(function (err) {
      we.log.error('Error in delete url alias:', err);
      done();
    });
  }
}

module.exports = alias;<|endoftext|>


<commit_before>module.exports = function(sails) {

	/**
	 * Module dependencies.
	 */

	var _ = require('lodash'),
		util = require('../util'),
		EventEmitter = require('events').EventEmitter;

	/**
	 * Expose new instance of `Router`
	 *
	 * @api private
	 */

	return new Router();

	/**
	 * Initialize a new `Router`
	 *
	 * @param {Object} options
	 * @api private
	 */

	function Router (options) {

		/**
		 * Instantiate a Express app just to get some of that sweet, sweet routing goodness
		 * (this Express app instance will not be used for listening for HTTP requests;
		 * instead, one or more delegate servers can be attached)
		 *
		 */

		// Requires calling of load() before use, due to dynamic loading of NODE_ENV
		var expressApp;

		/**
		 * Expose a new Router
		 *
		 * Link Express HTTP requests to a function which handles them
		 *
		 * @api public
		 */

		Router.prototype.load = function(cb) {

			sails.log.verbose('Loading router...');

			// Required for dynamic NODE_ENV setting via command line args
			expressApp = require('express')();

			// Maintain a reference to the static route config
			this.staticRoutes = sails.config.routes;

			// Save reference to sails logger
			this.log = sails.log;

			// Save self-reference in sails
			sails.router = this;

			// Make slave router accesible
			sails.router._app = expressApp;

			// Wipe any existing routes and bind them anew
			this.flush();

			// Listen for requests
			sails.on('router:request', this.route);

			cb();
		};

		/*
		 * Set up a `request` listener which can be used to trigger routes
		 *
		 * NOTE: this should only be used if the request handler does not have its own router.
		 * (this approach also dramatically simplifies unit testing!)
		 *
		 * The optimal behavior for Express, for instance, is to listen to `router:bind`
		 * and use the built-in router at lift-time, whereas Socket.io needs to use the
		 * `router:request` event to simulate a connect-style router since it
		 * can't bind dynamic routes ahead of time.
		 *
		 * By default, params and IO methods like res.send() are noops that should be overridden.
		 *
		 * Keep in mind that, if `route` is not used, the implementing server is responsible
		 * for routing to Sails' default `next(foo)` handler.
		 *
		 * @param {Object} req
		 * @param {Object} res
		 * @param {Function} cb [optional- used to populate default res.send() behavior]
		 * @api private
		 */

		Router.prototype.route = function(req, res, cb) {
			cb = util.optional(cb);

			// Bundle raw callback function
			res._cb = cb;

			// Make sure request and response objects have reasonable defaults
			// (will use the supplied definitions if possible)
			req = reasonableDefaultRequest(req);
			res = reasonableDefaultResponse(res);

			// Use our slave router to route the request
			expressApp.router(req, res, this.wildcard(req, res));

		};

		/**
		 * Bind new route(s)
		 *
		 * @param {String|RegExp} path
		 * @param {String|Object|Array|Function} bindTo
		 * @param {String} verb
		 * @api private
		 */

		Router.prototype.bind = require('./bind')(sails);

		/**
		 * Unbind existing route
		 *
		 * @param {Object} route
		 * @param {Integer} index
		 * @api private
		 */

		Router.prototype.unbind = function(route, index) {

			// Inform servers that route should be ignored
			sails.emit('router:unbind', route);

			// Remove route in internal router
			var newRoutes = [];
			_.each(expressApp.routes[route.method], function(expressRoute) {
				if (expressRoute.path != route.path) {
					newRoutes.push(expressRoute);
				}
			});
			expressApp.routes[route.method] = newRoutes;

		};

		/**
		 * Unbind all routes currently attached to the router
		 *
		 * @param {String} verb [optional]
		 * @api private
		 */

		Router.prototype.reset = function(verb) {

			// If no verb was specified, unbind everything
			if (!verb) {
				_.each(expressApp.routes, function(routes, method) {
					this.reset(method);
				}, this);

				return;
			}

			// Unbind each route for the specified HTTP verb
			_.each(expressApp.routes[verb] || [], this.unbind, this);

		};

		/**
		 * Wipe everything and bind routes.
		 *
		 * @api private
		 */

		Router.prototype.flush = function() {

			this.reset();

			// Fired before static routes are bound
			sails.emit('router:before');

			// Use specified path to bind static routes
			_.each(this.staticRoutes, function(target, path) {
				this.bind(path, target);
			}, this);

			// Fired after static routes are bound,
			// but BEFORE implicit routes
			sails.emit('router:beforeImplicit');

			// Fired after static routes are bound
			sails.emit('router:after');
		};

		/**
		 * Handle an unmatched `next()`, `next('foo')`, or `next('foo', errorCode)`
		 *
		 * @api private
		 */

		Router.prototype.wildcard = function generateHandler (req, res) {
			return function handleUnmatchedNext(status) {

				// Default server error handler
				if (status) {
					return sails.config[500](status, req, res);
				}

				// Default 'not found' handler
				return sails.config[404](req, res);
			};
		};

		// Bind the context of all instance methods
		_.bindAll(this);

	}

	/**
	 * Ensure that request object has a minimum set of reasonable defaults
	 */

	function reasonableDefaultRequest(req) {
		return _.defaults(req || {}, {
			params: {},
			param: function(paramName) {
				return req.params[paramName];
			},
			wantsJSON: true,
			method: 'get'
		});
	}

	/**
	 * Ensure that response object has a minimum set of reasonable defaults
	 */

	function reasonableDefaultResponse(res) {
		return _.defaults(res || {}, {
			send: function(body, status) {
				res._cb(body, status);
			},
			json: function(body, status) {
				var json;

				try {
					json = JSON.stringify(body);
				} catch (e) {
					return res.send(e, 500);
				}

				res.send(json, status);
			}
		});
	}

};<commit_msg>Track request start time.<commit_after>module.exports = function(sails) {

	/**
	 * Module dependencies.
	 */

	var _ = require('lodash'),
		util = require('../util'),
		EventEmitter = require('events').EventEmitter;

	/**
	 * Expose new instance of `Router`
	 *
	 * @api private
	 */

	return new Router();

	/**
	 * Initialize a new `Router`
	 *
	 * @param {Object} options
	 * @api private
	 */

	function Router (options) {

		/**
		 * Instantiate a Express app just to get some of that sweet, sweet routing goodness
		 * (this Express app instance will not be used for listening for HTTP requests;
		 * instead, one or more delegate servers can be attached)
		 *
		 */

		// Requires calling of load() before use, due to dynamic loading of NODE_ENV
		var expressApp;

		/**
		 * Expose a new Router
		 *
		 * Link Express HTTP requests to a function which handles them
		 *
		 * @api public
		 */

		Router.prototype.load = function(cb) {

			sails.log.verbose('Loading router...');

			// Required for dynamic NODE_ENV setting via command line args
			expressApp = require('express')();

			// Maintain a reference to the static route config
			this.staticRoutes = sails.config.routes;

			// Save reference to sails logger
			this.log = sails.log;

			// Save self-reference in sails
			sails.router = this;

			// Make slave router accesible
			sails.router._app = expressApp;

			// Wipe any existing routes and bind them anew
			this.flush();

			// Listen for requests
			sails.on('router:request', this.route);

			cb();
		};

		/*
		 * Set up a `request` listener which can be used to trigger routes
		 *
		 * NOTE: this should only be used if the request handler does not have its own router.
		 * (this approach also dramatically simplifies unit testing!)
		 *
		 * The optimal behavior for Express, for instance, is to listen to `router:bind`
		 * and use the built-in router at lift-time, whereas Socket.io needs to use the
		 * `router:request` event to simulate a connect-style router since it
		 * can't bind dynamic routes ahead of time.
		 *
		 * By default, params and IO methods like res.send() are noops that should be overridden.
		 *
		 * Keep in mind that, if `route` is not used, the implementing server is responsible
		 * for routing to Sails' default `next(foo)` handler.
		 *
		 * @param {Object} req
		 * @param {Object} res
		 * @param {Function} cb [optional- used to populate default res.send() behavior]
		 * @api private
		 */

		Router.prototype.route = function(req, res, cb) {
			cb = util.optional(cb);

			// Bundle raw callback function
			res._cb = cb;

			// Track request start time
			req._startTime = new Date();

			// Make sure request and response objects have reasonable defaults
			// (will use the supplied definitions if possible)
			req = reasonableDefaultRequest(req);
			res = reasonableDefaultResponse(res);

			// Use our slave router to route the request
			expressApp.router(req, res, this.wildcard(req, res));

		};

		/**
		 * Bind new route(s)
		 *
		 * @param {String|RegExp} path
		 * @param {String|Object|Array|Function} bindTo
		 * @param {String} verb
		 * @api private
		 */

		Router.prototype.bind = require('./bind')(sails);

		/**
		 * Unbind existing route
		 *
		 * @param {Object} route
		 * @param {Integer} index
		 * @api private
		 */

		Router.prototype.unbind = function(route, index) {

			// Inform servers that route should be ignored
			sails.emit('router:unbind', route);

			// Remove route in internal router
			var newRoutes = [];
			_.each(expressApp.routes[route.method], function(expressRoute) {
				if (expressRoute.path != route.path) {
					newRoutes.push(expressRoute);
				}
			});
			expressApp.routes[route.method] = newRoutes;

		};

		/**
		 * Unbind all routes currently attached to the router
		 *
		 * @param {String} verb [optional]
		 * @api private
		 */

		Router.prototype.reset = function(verb) {

			// If no verb was specified, unbind everything
			if (!verb) {
				_.each(expressApp.routes, function(routes, method) {
					this.reset(method);
				}, this);

				return;
			}

			// Unbind each route for the specified HTTP verb
			_.each(expressApp.routes[verb] || [], this.unbind, this);

		};

		/**
		 * Wipe everything and bind routes.
		 *
		 * @api private
		 */

		Router.prototype.flush = function() {

			this.reset();

			// Fired before static routes are bound
			sails.emit('router:before');

			// Use specified path to bind static routes
			_.each(this.staticRoutes, function(target, path) {
				this.bind(path, target);
			}, this);

			// Fired after static routes are bound,
			// but BEFORE implicit routes
			sails.emit('router:beforeImplicit');

			// Fired after static routes are bound
			sails.emit('router:after');
		};

		/**
		 * Handle an unmatched `next()`, `next('foo')`, or `next('foo', errorCode)`
		 *
		 * @api private
		 */

		Router.prototype.wildcard = function generateHandler (req, res) {
			return function handleUnmatchedNext(status) {

				// Default server error handler
				if (status) {
					return sails.config[500](status, req, res);
				}

				// Default 'not found' handler
				return sails.config[404](req, res);
			};
		};

		// Bind the context of all instance methods
		_.bindAll(this);

	}

	/**
	 * Ensure that request object has a minimum set of reasonable defaults
	 */

	function reasonableDefaultRequest(req) {
		return _.defaults(req || {}, {
			params: {},
			param: function(paramName) {
				return req.params[paramName];
			},
			wantsJSON: true,
			method: 'get'
		});
	}

	/**
	 * Ensure that response object has a minimum set of reasonable defaults
	 */

	function reasonableDefaultResponse(res) {
		return _.defaults(res || {}, {
			send: function(body, status) {
				res._cb(body, status);
			},
			json: function(body, status) {
				var json;

				try {
					json = JSON.stringify(body);
				} catch (e) {
					return res.send(e, 500);
				}

				res.send(json, status);
			}
		});
	}

};<|endoftext|>