UNPKG

prisme-flow

Version:

prisme platform flow engine

305 lines (288 loc) 9.82 kB
/** * Created by prisme.io on 09/06/2017. */ module.exports = function (RED) { 'use strict' var request = require('request') var clone = require('clone') function GoogleDirectionsNode (n) { RED.nodes.createNode(this, n) var node = this this.googleAPI = RED.nodes.getNode(n.googleAPI) this.on('input', function (msg) { var url, queryParams, key, origin, destination, mode, waypoints, alternatives, avoid, language, units, region, departure_time, arrival_time, transit_mode, transit_routing_preferences if (this.googleAPI && this.googleAPI.credentials && this.googleAPI.credentials.key) { key = this.googleAPI.credentials.key } else if (msg.key) { key = msg.key } origin = n.origin || msg.origin destination = n.destination || msg.destination mode = n.mode || msg.mode waypoints = n.waypoints || msg.waypoints alternatives = n.alternatives || msg.alternatives avoid = n.avoid || msg.avoid language = n.language || msg.language units = n.units || msg.units region = n.region || msg.region departure_time = n.departure_time || msg.departure_time arrival_time = n.arrival_time || msg.arrival_time transit_mode = n.transit_mode || msg.transit_mode transit_routing_preferences = n.transit_routing_preferences || msg.transit_routing_preferences function processInput () { queryParams = {} if (key) { queryParams.key = key } directionsRequest(function (response) { if (response) { node.send(response) } }) } function directionsRequest (cb) { url = 'https://maps.googleapis.com/maps/api/directions/json' if (!origin) { throwNodeError({ code: 400, message: RED._('directions.error.no-origin'), status: 'MISSING_VALUES' }, msg) return } if (!destination) { throwNodeError({ code: 400, message: RED._('Please supply an origin value'), status: 'MISSING_VALUES' }, msg) return } queryParams.origin = origin queryParams.destination = destination if (mode) { queryParams.mode = mode } if (waypoints) { queryParams.waypoints = waypoints } if (alternatives) { queryParams.alternatives = alternatives } if (avoid) { queryParams.avoid = avoid } if (language) { queryParams.language = language } if (units) { queryParams.units = units } if (region) { queryParams.region = region } if (departure_time) { queryParams.departure_time = departure_time } if (arrival_time) { queryParams.arrival_time = arrival_time } if (transit_mode) { queryParams.transit_mode = transit_mode } if (transit_routing_preferences) { queryParams.transit_routing_preferences = transit_routing_preferences } // console.log(queryParams); sendReqToGoogle(function (err, data) { if (err) { // console.log(err); throwNodeError(err, msg) } else { handleDirectionsResponse(JSON.parse(data), function (msg) { cb(msg) }) } }) } function handleDirectionsResponse (data, cb) { var newMsg if (data.status == 'OK') { newMsg = cloneMsg(msg) // quick clone msg newMsg.payload = { routes: [], status: data.status } for (var i = 0; i < data.routes.length; i++) { newMsg.payload.routes.push(parseRoute(data.routes[i])) } newMsg.status = data.status newMsg.title = RED._('Travel directions via') + ' ' + newMsg.payload.routes[0].summary newMsg.description = 'Travel directions via ' + newMsg.payload.routes[0].summary newMsg.distance = newMsg.payload.routes[0].legs[0].distance.value newMsg.duration = newMsg.payload.routes[0].legs[0].duration.value newMsg.location = { start: { address: newMsg.payload.routes[0].legs[0].start_location.address, lat: newMsg.payload.routes[0].legs[0].start_location.lat, lon: newMsg.payload.routes[0].legs[0].start_location.lon }, end: { address: newMsg.payload.routes[0].legs[0].end_location.address, lat: newMsg.payload.routes[0].legs[0].end_location.lat, lon: newMsg.payload.routes[0].legs[0].end_location.lon } } cb(newMsg) } else if (data.status == 'ZERO_RESULTS') { newMsg = cloneMsg(msg) // quick clone msg newMsg.payload = { status: 'ZERO_RESULTS' } newMsg.title = 'ZERO_RESULTS' newMsg.description = 'ZERO_RESULTS' cb(newMsg) } else { var error = {} error.status = data.status switch (data.status) { case 'NOT_FOUND': error.code = 400 error.message = RED._('Could not find origin, destination, or waypoint') break case 'MAX_WAYPOINTS_EXCEEDED': error.code = 400 error.message = RED._('Too many waypoints provided. The maximum allowed is 8') break case 'INVALID_REQUEST': error.code = 400 error.message = RED._('Invalid request. Check for an invalid parameter or parameter value') break case 'OVER_QUERY_REQUEST': error.code = 429 error.message = RED._('Too many requests from provided application key') break case 'REQUEST_DENIED': error.code = 400 error.message = RED._('Request denied by Google') break case 'UNKNOWN_ERROR': error.code = 500 error.message = RED._('An unknown error occured. Please try again') break default: error.code = 500 error.message = RED._('An unknown error occured. Please try again') } throwNodeError({ code: 400, message: RED._('Please supply an destination value'), status: 'MISSING_VALUES' }, msg) } } function sendReqToGoogle (cb) { request.get({ url: url, qs: queryParams, method: 'GET' }, function (err, resp, body) { cb(err, body) }) } function parseRoute (route) { var parsedRoute = {} parsedRoute.copyrights = route.copyrights parsedRoute.summary = route.summary parsedRoute.bounds = { northeast: { lat: route.bounds.northeast.lat, lon: route.bounds.northeast.lng }, southwest: { lat: route.bounds.southwest.lat, lon: route.bounds.southwest.lng } } if (route.warnings.length > 0) { parsedRoute.warnings = route.warnings } if (route.waypoint_order.length > 0) { parsedRoute.waypoint_order = route.waypoint_order } parsedRoute.fare = route.fare parsedRoute.legs = [] for (var i = 0; i < route.legs.length; i++) { parsedRoute.legs.push(parseLeg(route.legs[i])) } return parsedRoute } function parseLeg (leg) { var parsedLeg = {} parsedLeg.distance = leg.distance parsedLeg.duration = leg.duration parsedLeg.duration_in_traffic = leg.duration_in_traffic parsedLeg.departure_time = leg.departure_time parsedLeg.arrival_time = leg.arrival_time parsedLeg.start_location = { address: leg.start_address, lat: leg.start_location.lat, lon: leg.start_location.lng } parsedLeg.end_location = { address: leg.end_address, lat: leg.end_location.lat, lon: leg.end_location.lng } parsedLeg.steps = [] for (var i = 0; i < leg.steps.length; i++) { parsedLeg.steps.push(parseStep(leg.steps[i])) } return parsedLeg } function parseStep (step) { var parsedStep = {} parsedStep.distance = step.distance parsedStep.duration = step.duration parsedStep.start_location = { lat: step.start_location.lat, lon: step.start_location.lng } parsedStep.end_location = { lat: step.end_location.lat, lon: step.end_location.lng } parsedStep.html_instructions = step.html_instructions parsedStep.maneuver = step.maneuver parsedStep.travel_mode = step.travel_mode if (parsedStep.travel_mode == 'transit') { parsedStep.transit_details = step.transit_details } return parsedStep } processInput() }) function throwNodeError (err, msg) { node.status({fill: 'red', shape: 'ring', text: 'failed'}) msg.error = err node.error(err, msg) } } RED.nodes.registerType('google directions', GoogleDirectionsNode) function cloneMsg (msg) { var req = msg.req var res = msg.res delete msg.req delete msg.res var m = clone(msg) if (req) { m.req = req msg.req = req } if (res) { m.res = res msg.res = res } return m } }