diff --git a/package.json b/package.json index ed2a5dc..e6486e4 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "passport": "^0.3.2", "passport-auth0": "^0.6.0", "path": "^0.12.7", + "sendbird-nodejs": "^1.0.0", "serve-static": "^1.11.1", "winston": "^2.1.1" }, diff --git a/src/config/param-validation.js b/src/config/param-validation.js index 189283a..b7105d9 100644 --- a/src/config/param-validation.js +++ b/src/config/param-validation.js @@ -46,5 +46,11 @@ export default { params: { flightname: flightName } + }, + + chat: { + params: { + flightname: flightName + } } }; diff --git a/src/index.js b/src/index.js index bbf5e88..a7f90d5 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,8 @@ const path = require('path'); Promise.promisifyAll(mongoose); // connect to mongo db -winston.log('info', 'starting api service.'); +winston.log('info', 'gomake-api service started'); + mongoose.connect(config.db, { server: { socketOptions: { keepAlive: 1 } } }); mongoose.connection.on('error', () => { winston.log('error', `Timestamp: ${new Date()} | ` + diff --git a/src/server/controllers/chat.js b/src/server/controllers/chat.js new file mode 100644 index 0000000..00eaaba --- /dev/null +++ b/src/server/controllers/chat.js @@ -0,0 +1,80 @@ +'use strict'; + +import Flight from '../models/flight'; +import contentResponse from '../helpers/APIResponse'; +import SendBird from 'sendbird-nodejs'; + +const API_TOKEN = process.env.GM_SENDBIRD_API_TOKEN; +const CREATE_ERROR = 405; +const CREATE_USERS_NOT_FOUND = 404; +const CREATE_SUCCESS = 200; + +function createFlightChannel(req, res) { + const flightName = req.params.flightname.toUpperCase(); + const getFlight = getFlightFromFlightName(flightName); + const sb = getSendBirdInstance(); + + getFlight + .then(getUsersForFlight) + .then((userIds) => { + const options = { + name: flightName, + custom_type: flightName, + user_ids: userIds, + is_distinct: true + }; + return sb.groupChannels.create(options); + }) + .then((response) => { + if (response) { + const channelUrl = response.channel_url; + res.send(CREATE_SUCCESS, contentResponse({ channel_url: channelUrl })); + } else { + res.sendStatus(CREATE_ERROR); + } + }, (err) => { + console.log(err); + res.sendStatus(err); + }); +} + +function getFlightFromFlightName(flightName) { + return Flight.getFlightFromFlightName(flightName); +} + +function getSendBirdInstance() { + return new SendBird(API_TOKEN); +} + +function getUsersForFlight(foundFlight) { + if (foundFlight) { + const userIds = foundFlight.userIds || []; + if (!!!userIds.length) { + return Promise.reject(CREATE_USERS_NOT_FOUND); + } + return Promise.resolve(userIds); + } + return Promise.reject(CREATE_ERROR); +} + +function getFlightChannel(req, res) { + const flightName = req.params.flightname.toUpperCase(); + getChannelForFlight(flightName) + .then((response) => { + const channels = response.channels; + res.json(contentResponse(channels)); + }); +} + +function getChannelForFlight(flightName) { + const sb = getSendBirdInstance(); + const options = { + custom_type: flightName + }; + return sb.groupChannels.list(options); +} + +export default { + createFlightChannel, + getFlightChannel +}; diff --git a/src/server/models/flight.js b/src/server/models/flight.js index d57e270..55ba58a 100644 --- a/src/server/models/flight.js +++ b/src/server/models/flight.js @@ -9,7 +9,8 @@ const FlightSchema = new mongoose.Schema({ launchLocation: mongoose.Schema.Types.GeoJSON, launchAltitude: Number, registeredTrackers: Array, - deviceIds: Array + deviceIds: Array, + userIds: Array }, { timestamps: true }); diff --git a/src/server/routes/flight.js b/src/server/routes/flight.js index 486ac96..14fc9bd 100644 --- a/src/server/routes/flight.js +++ b/src/server/routes/flight.js @@ -3,6 +3,7 @@ import validate from 'express-validation'; import telemetryCtrl from '../controllers/telemetry'; import flightInfoCtrl from '../controllers/flight'; import historyCtrl from '../controllers/history'; +import chat from '../controllers/chat'; import paramValidation from '../../config/param-validation'; import authentication from '../middleware/authentication'; @@ -16,7 +17,6 @@ router.route('/:flightname') router.route('/:flightname') .post(validate(paramValidation.flightInfo), flightInfoCtrl.postFlightInfo); - /** GET flight telemetry */ router.route('/:flightname/telemetry') .get(validate(paramValidation.telemetry), telemetryCtrl.getTelemetry); @@ -29,4 +29,20 @@ router.route('/:flightname/telemetry') router.route('/:flightname/history') .get(validate(paramValidation.history), historyCtrl.getFlightHistory); +/** POST flight chat: create group_channel for flight if does not exist */ +router.route('/:flightname/chat') + .post(validate(paramValidation.chat), chat.createFlightChannel); + +/** GET flight chat: get group_channel for flight */ +router.route('/:flightname/chat') + .get(validate(paramValidation.chat), chat.getFlightChannel); + +/** POST flight user ids: create group_channel for flight if does not exist */ +router.route('/:flightname/users/:userId') + .post(validate(paramValidation.chat), chat.createFlightChannel); + +/** GET flight user ids: get group_channel for flight */ +router.route('/:flightname/users/:userId') + .get(validate(paramValidation.chat), chat.getFlightChannel); + export default router; diff --git a/src/server/routes/history.js b/src/server/routes/history.js new file mode 100644 index 0000000..e69de29