PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/app.js

https://bitbucket.org/mpuckett/iostudio-whiteboard
JavaScript | 408 lines | 259 code | 108 blank | 41 comment | 5 complexity | c6b79191e80f20b3bc4d36e16c496b61 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, MIT
  1. /**
  2. * Module dependencies.
  3. */
  4. var express = require('express'),
  5. routes = require('./routes'),
  6. user = require('./routes/user'),
  7. http = require('http'),
  8. path = require('path'),
  9. socket_io = require('socket.io').listen(8080),
  10. _ = require('underscore'),
  11. Backbone = require('backbone'),
  12. fs = require('fs'),
  13. tropo_webapi = require('tropo-webapi'),
  14. appFiles = require('./server/files'),
  15. appUsers = require('./server/users'),
  16. appChat = require('./server/chat'),
  17. appDraw = require('./server/draw');
  18. //, mongodb = require('mongodb');
  19. /**
  20. * Database setup
  21. */
  22. //var db = mongodb.createConnection('localhost', 'io-whiteboard');
  23. /**
  24. * Express setup
  25. */
  26. var allowCrossDomain = function(req, res, next) {
  27. res.header('Access-Control-Allow-Origin', '*');
  28. res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
  29. res.header('Access-Control-Allow-Headers', 'Content-Type');
  30. next();
  31. };
  32. var app = express();
  33. app.configure(function () {
  34. app.set('port', process.env.PORT || 3000);
  35. app.set('views', __dirname + '/views');
  36. app.set('view engine', 'html');
  37. app.engine('html', require('ejs').__express);
  38. app.use(express.favicon());
  39. app.use(express.logger('dev'));
  40. app.use(express.bodyParser());
  41. app.use(express.methodOverride());
  42. app.use(allowCrossDomain);
  43. app.use(app.router);
  44. app.use(express.static(path.join(__dirname, 'public')));
  45. });
  46. app.configure('development', function () {
  47. app.use(express.errorHandler());
  48. });
  49. app.post('/tropo', function(req, res){
  50. var tropo = new TropoWebAPI();
  51. var phoneNumber = req.body.session.from.id;
  52. // on call start, add phone user to users collection
  53. appController.trigger('_userSessionStarted', {
  54. id: phoneNumber,
  55. image: {
  56. 'data': '/images/default-phone-image.gif'
  57. }
  58. });
  59. tropo.say("Welcome. Hit pound at any time to record a new message.");
  60. tropo.on("continue", null, "/listen?id="+phoneNumber, true);
  61. tropo.on('hangup', null, '/hangup?id='+phoneNumber, true);
  62. res.send(TropoJSON(tropo));
  63. });
  64. app.post('/listen', function(req, res){
  65. var tropo = new TropoWebAPI();
  66. var phoneNumber = req.query.id;
  67. //var answer = req.body['result']['actions']['value'];
  68. var say = new Say('');
  69. var choices = new Choices(null, null, '#');
  70. tropo.ask(choices, null, null, null, 'poll', null, null, say, 5, null);
  71. tropo.on('continue', null, '/record?id='+phoneNumber, true);
  72. tropo.on('incomplete', null, '/messages?id='+phoneNumber, true);
  73. tropo.on('hangup', null, '/hangup?id='+phoneNumber, true);
  74. res.send(TropoJSON(tropo));
  75. });
  76. app.post('/record', function (req,res) {
  77. var tropo = new TropoWebAPI();
  78. var phoneNumber = req.query.id;
  79. var say = new Say('Press pound after recording your message.');
  80. var transcription = {"id":phoneNumber, "url":"http://54.243.182.246:3000/call"};
  81. var choices = new Choices(null,null,'#');
  82. //tropo.record(null, null, true, choices, null, 7.0, 120.0, null, null, "recording", null, say, 10.0, transcription, "ftp://ftp.pickpuck.com/pickpuck.com/recording.mp3", "Agent106!", "mcpuck");
  83. tropo.record(null, null, true, choices, 'audio/mp3', 5, 30, null, null, "recording", null, say, 5, transcription, "http://54.243.182.246:3000/upload?id="+phoneNumber, null, null);
  84. tropo.on('continue', null, '/messages?id='+phoneNumber, true);
  85. tropo.on('hangup', null, '/hangup?id='+phoneNumber, true);
  86. res.send(TropoJSON(tropo));
  87. });
  88. app.post('/upload', function (req,res) {
  89. var phoneNumber = req.query.id;
  90. var fileName = req.files.filename.name;
  91. fs.readFile(req.files.filename.path, function (err, data) {
  92. var newPath = __dirname + "/public/recordings/" + fileName;
  93. console.log(newPath);
  94. fs.writeFile(newPath, data, function (err) {
  95. appController.trigger('_chatMessageAdded', {
  96. user: {
  97. id: phoneNumber
  98. },
  99. message: '(Transcribing audio...)',
  100. file: '/recordings/'+fileName
  101. });
  102. res.redirect("back");
  103. });
  104. });
  105. });
  106. app.post('/messages', function (req,res) {
  107. var tropo = new TropoWebAPI();
  108. var phoneNumber = req.query.id;
  109. var userModel = appController.usersController.usersCollection.get(phoneNumber);
  110. var user = userModel.toJSON();
  111. var messagesCollection = appController.chatController.messagesCollection;
  112. var messagesSinceLastMessage = messagesCollection.filter(function (message, index) {
  113. return (index > user.lastMessage) && ( message.get('user').id !== phoneNumber );
  114. });
  115. console.log(messagesSinceLastMessage);
  116. _.each(messagesSinceLastMessage, function (message) {
  117. console.log('a message since last message', message.toJSON());
  118. tropo.say(message.get('message'));
  119. });
  120. userModel.set('lastMessage', messagesCollection.length-1);
  121. tropo.on('continue', null, '/listen?id='+phoneNumber, null);
  122. tropo.on('hangup', null, '/hangup?id='+phoneNumber, true);
  123. res.send(TropoJSON(tropo));
  124. });
  125. app.post('/hangup', function (req,res) {
  126. var tropo = new TropoWebAPI();
  127. var phoneNumber = req.query.id;
  128. console.log('HANGUP', phoneNumber);
  129. appController.usersController.remove({id:phoneNumber});
  130. res.send(TropoJSON(tropo));
  131. });
  132. app.get('/', routes.index);
  133. app.get('/users', user.list);
  134. http.createServer(app)
  135. .listen(app.get('port'), function () {
  136. console.log("Express server listening on port " + app.get('port'));
  137. });
  138. /**
  139. Backbone setup
  140. */
  141. // Add update method to all models
  142. Backbone.Controller = Backbone.View;
  143. Backbone.Model.prototype.update = function(model){
  144. var t = this;
  145. // update or add all new values
  146. _.each(model, function (value, attribute) {
  147. t.set(attribute, value);
  148. });
  149. // if new value is missing, delete old value
  150. _.each(this.attributes, function (value, attribute) {
  151. if (!model[attribute]) {
  152. t.unset(attribute);
  153. }
  154. });
  155. };
  156. // Make Backbone DOM-independent
  157. Backbone.View.prototype._ensureElement = function () {};
  158. // import Files
  159. appFiles.init({
  160. _: _,
  161. Backbone: Backbone,
  162. fs: fs
  163. });
  164. // import Users
  165. appUsers.init({
  166. _: _,
  167. Backbone: Backbone
  168. });
  169. // import Chat
  170. appChat.init({
  171. _: _,
  172. Backbone: Backbone
  173. });
  174. appDraw.init({
  175. _: _,
  176. Backbone: Backbone
  177. });
  178. // App
  179. var AppController = Backbone.Model.extend({
  180. initialize: function () {
  181. var t = this;
  182. var filesController = this.filesController =new FilesController();
  183. var usersController = this.usersController = new UsersController();
  184. var chatController = this.chatController = new ChatController();
  185. var drawController = this.drawController = new DrawController();
  186. // file listeners
  187. filesController.on('_newFile', function (file) {
  188. t.notify( 'newFile', file );
  189. });
  190. filesController.on('_error', function (params) {
  191. if (params.user) {
  192. t.message(params.user, 'error', params.error);
  193. } else {
  194. t.notify('error', params.error);
  195. }
  196. });
  197. // user listeners
  198. usersController.on('_userAdded', function (user) {
  199. t.notify('userAdded', user);
  200. });
  201. usersController.on('_userRemoved', function (user) {
  202. t.notify('userRemoved', user);
  203. });
  204. usersController.on('_userUpdated', function (user) {
  205. t.notify('userUpdated', user);
  206. chatController.update(user, { type: 'user' });
  207. });
  208. // socket notifications
  209. this.on('_fileAdded', function (file) {
  210. filesController.trigger('fileAdded', file);
  211. });
  212. this.on('_userSessionStarted', function (user) {
  213. t.message(user.id, 'getAllUsers', usersController.render());
  214. t.message(user.id, 'getAllFiles', filesController.render());
  215. t.message(user.id, 'getAllMessages', chatController.render());
  216. usersController.add(user);
  217. });
  218. this.on('_userSessionEnded', function (user) {
  219. usersController.remove(user);
  220. });
  221. this.on('_userUpdated', function (user) {
  222. usersController.update(user);
  223. });
  224. // chat listeners
  225. this.on('_chatMessageAdded', function (message) {
  226. chatController.trigger('messageAdded', message);
  227. });
  228. this.on('_chatMessageUpdated', function (message) {
  229. chatController.trigger('chatMessageUpdated', message);
  230. });
  231. chatController.on('_chatMessageAdded', function (message) {
  232. console.log('chat message added', message);
  233. t.notify('chatMessageAdded', message);
  234. });
  235. chatController.on('_chatMessageUpdated', function (message) {
  236. t.notify('chatMessageUpdated', message);
  237. });
  238. drawController.on('_lineAdded', function (line) {
  239. t.notify('newLineCoordinate', line);
  240. });
  241. this.notify('reload');
  242. },
  243. notify: function (message, data) {
  244. socket_io.sockets.emit('_' + message, data);
  245. },
  246. message: function (user, message, data) {
  247. socket_io.sockets.socket(user).emit('_' + message, data);
  248. }
  249. });
  250. appController = new AppController();
  251. /**
  252. Tropo setup
  253. */
  254. app.post('/call', function (req, res) {
  255. var tropo = new TropoWebAPI();
  256. var phoneNumber = req.body.result.identifier;
  257. /*var user = appController.usersController.usersCollection.get(phoneNumber);
  258. if (user.length > 0) {
  259. user = user[0].toJSON();
  260. } else {
  261. user = { id: phoneNumber };
  262. }*/
  263. var messagesCollection = appController.chatController.messagesCollection;
  264. var userMessagesCollection = messagesCollection.filter(function (message, index) {
  265. return message.get('user').id === phoneNumber;
  266. });
  267. console.log(userMessagesCollection);
  268. var message = _.last(userMessagesCollection).toJSON();
  269. message.message = req.body.result.transcription;
  270. console.log(message);
  271. console.log(req.body.result.transcription);
  272. appController.chatController.update(message);
  273. tropo.on("continue", null, "/listen?id="+phoneNumber, true);
  274. res.send(TropoJSON(tropo));
  275. });
  276. /**
  277. Socket.io setup
  278. */
  279. socket_io.sockets.on('connection', function (socket) {
  280. appController.trigger('_userSessionStarted', {id:socket.id});
  281. socket.on('disconnect', function () {
  282. appController.trigger('_userSessionEnded', {id:socket.id});
  283. });
  284. socket.on('fileAdded', function (data) {
  285. console.log(data);
  286. appController.trigger('_fileAdded', data);
  287. });
  288. socket.on('chatMessageAdded', function (data) {
  289. appController.trigger('_chatMessageAdded', data);
  290. });
  291. socket.on('reloadRequest', function (data) {
  292. appController.notify('reload');
  293. });
  294. socket.on('userUpdated', function (data) {
  295. appController.trigger('_userUpdated', data);
  296. });
  297. socket.on('newLineCoordinate', function (data) {
  298. appController.trigger('_newLineCoordinate', data);
  299. });
  300. });