├── .gitignore ├── .floo ├── .flooignore ├── public ├── js │ ├── index.js │ ├── controllers │ │ ├── video.js │ │ ├── videoAdmin.js │ │ └── chat.js │ └── services.js ├── admin.html ├── index.html ├── admin │ └── index.html └── css │ └── index.css ├── package.json ├── readme.md ├── app.js └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.floo: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://floobits.com/Celkam/MST4K" 3 | } -------------------------------------------------------------------------------- /.flooignore: -------------------------------------------------------------------------------- 1 | #* 2 | *.o 3 | *.pyc 4 | *~ 5 | extern/ 6 | node_modules/ 7 | tmp 8 | vendor/ -------------------------------------------------------------------------------- /public/js/index.js: -------------------------------------------------------------------------------- 1 | angular.module('theApp', ['chat', 'videoAdmin','video','services'] ); 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MST4K", 3 | "version": "1.0.0", 4 | "description": "A server package for serving up synced video in a browser with chat", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "Cassandra Cruz", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.12.3", 13 | "socket.io": "^1.3.5", 14 | "vid-streamer": "^1.0.0" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /public/js/controllers/video.js: -------------------------------------------------------------------------------- 1 | angular.module('video', []) 2 | .controller('videoController', function ($scope, socket) { 3 | $scope.video = document.getElementById('movie'); 4 | 5 | socket.on('movie:play', function() { 6 | $scope.video.play(); 7 | }); 8 | 9 | socket.on('movie:pause', function() { 10 | $scope.video.pause(); 11 | }); 12 | 13 | socket.on('movie:sync', function(data) { 14 | var current = $scope.video.currentTime; 15 | if (Math.abs(data - current) > 5) { 16 | $scope.video.currentTime = data; 17 | } 18 | 19 | // TODO: Make client option to ignore server sync 20 | }); 21 | 22 | 23 | 24 | }); 25 | -------------------------------------------------------------------------------- /public/js/services.js: -------------------------------------------------------------------------------- 1 | angular.module('services', []) 2 | .factory('socket', function ($rootScope) { 3 | var socket = io.connect(); 4 | return { 5 | on: function (eventName, callback) { 6 | socket.on(eventName, function () { 7 | var args = arguments; 8 | $rootScope.$apply(function () { 9 | callback.apply(socket, args); 10 | }); 11 | }); 12 | }, 13 | emit: function (eventName, data, callback) { 14 | socket.emit(eventName, data, function () { 15 | var args = arguments; 16 | $rootScope.$apply(function () { 17 | if (callback) { 18 | callback.apply(socket, args); 19 | } 20 | }); 21 | }) 22 | } 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Synopsis 2 | 3 | MST4K is a simple server package that lets you host a virtual theater website with viewer chat. 4 | 5 | ## Motivation 6 | 7 | As a Hack Reactor Remote student, we didn't really have any way to do the standard social nights that onsite students have. This is an attempt to facilitate that, with movie nights. 8 | 9 | ## Installation 10 | 11 | Inside the config folder, there will eventually be a sample file to config the Vid-Streamer middleware. For now, the configuration info can be found [here][1]. 12 | 13 | ## Tests 14 | 15 | Coming soon. 16 | 17 | ## Contributors 18 | 19 | This project will use the git flow model, but it is currently unenforced. Until then, only approved contributors will have their pull requests considered. 20 | 21 | ## License 22 | 23 | [ISC][2] 24 | 25 | [1]: https://github.com/meloncholy/vid-streamer 26 | [2]: http://opensource.org/licenses/ISC -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | // Require dependencies 2 | var express = require('express'); 3 | var app = express(); 4 | var http = require('http').Server(app); 5 | var io = require('socket.io')(http); 6 | // var vidStreamer = require('vid-streamer'); 7 | 8 | // Define main route 9 | app.use(express.static(__dirname + '/public')); 10 | // app.get('/videos/', vidStreamer); 11 | 12 | io.on('connection', function(socket) { 13 | socket.on('message', function(data) { 14 | console.log('incoming message: ', data); 15 | socket.broadcast.emit('message', data); 16 | }); 17 | 18 | socket.on('movie:play', function(data) { 19 | console.log('playing video'); 20 | socket.broadcast.emit('movie:play', data); 21 | }); 22 | 23 | socket.on('movie:pause', function(data) { 24 | console.log('pausing video'); 25 | socket.broadcast.emit('movie:pause', data); 26 | }); 27 | 28 | socket.on('movie:sync', function(data) { 29 | console.log('syncing video'); 30 | socket.broadcast.emit('movie:sync', data); 31 | }); 32 | }); 33 | 34 | 35 | http.listen(8080); 36 | 37 | -------------------------------------------------------------------------------- /public/js/controllers/videoAdmin.js: -------------------------------------------------------------------------------- 1 | angular.module('videoAdmin', []) 2 | .controller('videoAdminController', function ($scope, socket) { 3 | $scope.video = document.getElementById('movie'); 4 | 5 | $scope.video.addEventListener('playing', function() { 6 | socket.emit('movie:play', $scope.video.currentTime); 7 | }); 8 | 9 | $scope.video.addEventListener('pause', function() { 10 | socket.emit('movie:pause', $scope.video.currentTime); 11 | }); 12 | 13 | $scope.video.addEventListener('timeupdate', function() { 14 | socket.emit('movie:sync', $scope.video.currentTime); 15 | }); 16 | 17 | }); 18 | 19 | /* 20 | socket.on('movie:play', function() { 21 | $scope.video.play(); 22 | }); 23 | 24 | socket.on('movie:pause', function() { 25 | $scope.video.pause(); 26 | }); 27 | 28 | socket.on('movie:sync', function(data) { 29 | var current = $scope.video.currentTime; 30 | if (Math.abs(data-current) > 5) { 31 | $scope.video.fastseek(data); 32 | } 33 | 34 | // TODO: Make client option to ignore server sync 35 | }); 36 | */ 37 | 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 MST4K 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /public/js/controllers/chat.js: -------------------------------------------------------------------------------- 1 | angular.module('chat', []) 2 | .controller('chatController', function ($scope, socket) { 3 | 4 | // Socket listeners 5 | // ================ 6 | $scope.isThisTheEnterKey = function(e){ 7 | if(e.keyCode === 13){ 8 | $scope.sendMessage(); 9 | } 10 | } 11 | 12 | $scope.name; 13 | $scope.messages = $scope.messages || []; 14 | 15 | $scope.$watchCollection('messages', function() { 16 | console.log("change observed"); 17 | $scope.scrollMessages(); 18 | }); 19 | 20 | $scope.scrollMessages = function(){ 21 | setTimeout(function(){ 22 | document.getElementById('messagesHolder').scrollTop = 9999999; 23 | }, 110); 24 | 25 | } 26 | 27 | for(var i = 0; i < 50; i++){ 28 | $scope.messages.push({name:"someName", text: "this is a message from PHMessages. It's very very long to ensure that Cooper can see what line wrapping is doing inside of the index.html"}); 29 | } 30 | 31 | socket.on('message', function (message) { 32 | $scope.messages.push(message); 33 | // $scope.scrollMessages(); 34 | console.log(messages.length); 35 | }); 36 | 37 | // Methods published to the scope 38 | // ============================== 39 | 40 | $scope.changeName = function (newName) { 41 | $scope.name = newName; 42 | }; 43 | 44 | $scope.sendMessage = function () { 45 | socket.emit('message', { 46 | name: $scope.name, 47 | text: $scope.input 48 | }); 49 | 50 | // add the message to our model locally 51 | $scope.messages.push({ 52 | name: $scope.name, 53 | text: $scope.input 54 | }); 55 | 56 | // clear message box 57 | $scope.input = ''; 58 | 59 | }; 60 | }); 61 | -------------------------------------------------------------------------------- /public/admin.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |