Merge branch 'meteor-new-auth' of github.com:perroned/bigbluebutton into meteor-new-auth
Conflicts: labs/meteor-client/app/client/globals.coffee labs/meteor-client/app/client/views/chat/chat_bar.coffee labs/meteor-client/app/collections/chat.coffee labs/meteor-client/app/collections/meetings.coffee labs/meteor-client/app/collections/presentations.coffee labs/meteor-client/app/collections/shapes.coffee labs/meteor-client/app/collections/slides.coffee labs/meteor-client/app/collections/users.coffee
This commit is contained in:
commit
319a1247a1
2
labs/demos/lib/testapi.coffee
Normal file → Executable file
2
labs/demos/lib/testapi.coffee
Normal file → Executable file
@ -26,7 +26,7 @@ createParams.name = tempName
|
||||
createParams.meetingID = tempName
|
||||
|
||||
joinParams = {}
|
||||
joinParams.password = "ap"
|
||||
joinParams.password = "mp"
|
||||
joinParams.fullName = "Richard"
|
||||
joinParams.meetingID = tempName
|
||||
joinParams.redirect = false
|
||||
|
@ -20,12 +20,12 @@
|
||||
meet?.meetingName
|
||||
else null
|
||||
|
||||
@getTimeOfJoining = ->
|
||||
Meteor.Users.findOne({"user.userid": getInSession("userId")})?.user?.time_of_joining
|
||||
|
||||
@getTime = -> # returns epoch in ms
|
||||
(new Date).valueOf()
|
||||
|
||||
@getTimeOfJoining = ->
|
||||
Meteor.Users.findOne(_id: getInSession "DBID")?.user?.time_of_joining
|
||||
|
||||
@getUsersName = ->
|
||||
name = getInSession("userName") # check if we actually have one in the session
|
||||
if name? then name # great return it, no database query
|
||||
@ -58,6 +58,14 @@ Handlebars.registerHelper "getCurrentSlide", ->
|
||||
Handlebars.registerHelper "getCurrentUser", =>
|
||||
@window.getCurrentUserFromSession()
|
||||
|
||||
Handlebars.registerHelper "getHandRaiseStats", ->
|
||||
numRaised = Meteor.Users.find({'user.raise_hand':true}).fetch().length
|
||||
total = Meteor.Users.find().fetch().length
|
||||
percentageRaised = numRaised/total
|
||||
if numRaised > 0
|
||||
"#{numRaised} Hands Raised (#{percentageRaised}% of Attendees)"
|
||||
else false
|
||||
|
||||
# Allow access through all templates
|
||||
Handlebars.registerHelper "getInSession", (k) -> SessionAmplify.get k
|
||||
|
||||
@ -134,7 +142,7 @@ Handlebars.registerHelper "messageFontSize", ->
|
||||
|
||||
Handlebars.registerHelper "pointerLocation", ->
|
||||
currentPresentation = Meteor.Presentations.findOne({"presentation.current": true})
|
||||
currentPresentation.pointer
|
||||
currentPresentation?.pointer
|
||||
|
||||
Handlebars.registerHelper "setInSession", (k, v) -> SessionAmplify.set k, v
|
||||
|
||||
|
@ -29,11 +29,10 @@ Template.header.events
|
||||
# "click .settingsIcon": (event) ->
|
||||
# alert "settings"
|
||||
"click .raiseHand": (event) ->
|
||||
console.log "navbar raise own hand from client"
|
||||
Meteor.call('userRaiseHand', getInSession("meetingId"), getInSession("userId"))
|
||||
"click .lowerHand": (event) ->
|
||||
# loweredBy = @id # TODO! this must be the userid of the person lowering the hand - instructor/student
|
||||
loweredBy = getInSession("userId")
|
||||
Meteor.call('userLowerHand', getInSession("meetingId"), getInSession("userId"), loweredBy)
|
||||
Meteor.call('userLowerHand', getInSession("meetingId"), getInSession("userId"), getInSession("userId"))
|
||||
"click .whiteboardIcon": (event) ->
|
||||
toggleWhiteBoard()
|
||||
"mouseover #navbarMinimizedButton": (event) ->
|
||||
@ -47,8 +46,8 @@ Template.recordingStatus.rendered = ->
|
||||
$('button[rel=tooltip]').tooltip()
|
||||
|
||||
Template.main.helpers
|
||||
setTitle: ->
|
||||
document.title = "BigBlueButton HTML5"
|
||||
setTitle: ->
|
||||
document.title = "BigBlueButton #{window.getMeetingName() ? 'HTML5'}"
|
||||
|
||||
Template.makeButton.rendered = ->
|
||||
$('button[rel=tooltip]').tooltip()
|
||||
|
@ -55,7 +55,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if isCurrentUserRaisingHand}}
|
||||
{{> makeButton btn_class="lowerHand navbarIconToggleActive navbarButton" i_class="hand-up" rel="tooltip" data_placement="bottom" title="Lower your hand"}}
|
||||
{{> makeButton btn_class="lowerHand navbarIconToggleActive navbarButton" i_class="hand-down" rel="tooltip" data_placement="bottom" title="Lower your hand"}}
|
||||
{{else}}
|
||||
{{> makeButton btn_class="raiseHand navbarButton" i_class="hand-up" rel="tooltip" data_placement="bottom" title="Raise your hand"}}
|
||||
{{/if}}
|
||||
|
@ -66,6 +66,7 @@ bottomEntry{
|
||||
width: 80%;
|
||||
margin-top:6px;
|
||||
padding:5px;
|
||||
resize: none;
|
||||
}
|
||||
.optionsBar{
|
||||
padding-top:15px;
|
||||
|
@ -1,3 +1,4 @@
|
||||
#MuteAllUsers{}
|
||||
#users {
|
||||
margin-left: 0.5%;
|
||||
/*min-width:230px;*/
|
||||
|
@ -6,12 +6,13 @@
|
||||
chattingWith = getInSession('inChatWith')
|
||||
|
||||
if chattingWith isnt "PUBLIC_CHAT"
|
||||
dest = Meteor.Users.findOne("userId": chattingWith)
|
||||
# dest = Meteor.Users.findOne("userId": chattingWith)
|
||||
dest = Meteor.Users.findOne(_id: chattingWith)
|
||||
|
||||
messageForServer = { # construct message for server
|
||||
"message": message
|
||||
"chat_type": if chattingWith is "PUBLIC_CHAT" then "PUBLIC_CHAT" else "PRIVATE_CHAT"
|
||||
"from_userid": getInSession("userId")
|
||||
"from_userid": getInSession("DBID")
|
||||
"from_username": getUsersName()
|
||||
"from_tz_offset": "240"
|
||||
"to_username": if chattingWith is "PUBLIC_CHAT" then "public_chat_username" else dest.user.name
|
||||
@ -22,7 +23,8 @@
|
||||
# "from_color": "0x#{getInSession("messageColor")}"
|
||||
}
|
||||
|
||||
Meteor.call "sendChatMessagetoServer", getInSession("meetingId"), messageForServer
|
||||
console.log JSON.stringify messageForServer
|
||||
Meteor.call "sendChatMessagetoServer", getInSession("meetingId"), messageForServer, getInSession("userId")
|
||||
$('#newMessageInput').val '' # Clear message box
|
||||
|
||||
Template.chatInput.events
|
||||
@ -31,7 +33,7 @@ Template.chatInput.events
|
||||
|
||||
'keypress #newMessageInput': (event) -> # user pressed a button inside the chatbox
|
||||
if event.shiftKey and event.which is 13
|
||||
$("#newMessageInput").append("\n")
|
||||
$("#newMessageInput").append("\r") # Change newline character
|
||||
return
|
||||
|
||||
if event.which is 13 # Check for pressing enter to submit message
|
||||
@ -48,7 +50,7 @@ Template.chatbar.helpers
|
||||
greeting = "Welcome to #{getMeetingName()}!\r\r
|
||||
For help on using BigBlueButton see these (short) <a href='http://www.bigbluebutton.org/videos/' target='_blank'>tutorial videos</a>.\r\r
|
||||
To join the audio bridge click the headset icon (upper-left hand corner). Use a headset to avoid causing background noise for others.\r\r\r
|
||||
This server is running BigBlueButton #{getInSession 'bbbServerVersion'}."
|
||||
This server is running BigBlueButton #{getInSession 'bbbServerVersion'}.\r\r"
|
||||
|
||||
# This method returns all messages for the user. It looks at the session to determine whether the user is in
|
||||
#private or public chat. If true is passed, messages returned are from before the user joined. Else, the messages are from after the user joined
|
||||
@ -178,7 +180,6 @@ Template.tabButtons.events
|
||||
'click .gotUnreadMail': (event) ->
|
||||
chatTabs.update({userId: @userId}, {$set: {gotMail: false}})
|
||||
|
||||
|
||||
|
||||
Template.tabButtons.helpers
|
||||
makeTabButton: -> # create tab button for private chat or other such as options
|
||||
|
@ -1,6 +1,11 @@
|
||||
Template.displayUserIcons.events
|
||||
'click .raisedHandIcon': (event) ->
|
||||
Meteor.call('userLowerHand', getInSession("meetingId"), @user?.userid, getInSession("userId"))
|
||||
# the function to call 'userLowerHand'
|
||||
# the meeting id
|
||||
# the _id of the person whose land is to be lowered
|
||||
# the userId of the person who is lowering the hand
|
||||
console.log "lower hand- client click handler"
|
||||
Meteor.call('userLowerHand', getInSession("meetingId"), @_id, getInSession("userId"))
|
||||
|
||||
'click .muteIcon': (event) ->
|
||||
toggleMic @
|
||||
|
@ -32,13 +32,13 @@
|
||||
<td>{{#if user.presenter}}<span class="userListSettingIcon glyphicon glyphicon-picture" rel="tooltip" data-placement="bottom" title="{{user.name}} is the presenter"></span>{{/if}}</td>
|
||||
|
||||
<td>
|
||||
{{#if user.raise_hand}}
|
||||
{{#if isCurrentUser userId}}
|
||||
<!-- {{#if user.raise_hand}} -->
|
||||
<!-- {{#if isCurrentUser userId}} -->
|
||||
<span class="raisedHandIcon userListSettingIcon glyphicon glyphicon-hand-up" rel="tooltip" data-placement="bottom" title="Lower your hand"></span>
|
||||
{{else}}
|
||||
<span class="userListSettingIcon glyphicon glyphicon-hand-up" rel="tooltip" data-placement="bottom" title="{{user.name}} has raised their hand"></span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<!-- {{else}} -->
|
||||
<!-- <span class="userListSettingIcon glyphicon glyphicon-hand-up" rel="tooltip" data-placement="bottom" title="{{user.name}} has raised their hand"></span> -->
|
||||
<!-- {{/if}} -->
|
||||
<!-- {{/if}} -->
|
||||
</td>
|
||||
</template>
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
Template.usersList.helpers
|
||||
getMeetingSize: -> # Retreieve the number of users in the chat, or "error" string
|
||||
Meteor.Users.find().count()
|
||||
getMeetingSize: -> # Retreieve the number of users in the chat, or "error" string
|
||||
Meteor.Users.find().count()
|
||||
|
||||
Template.usersList.events
|
||||
'click #MuteAllUsers': (event) ->
|
||||
console.log "MuteAllUsers click handler"
|
||||
Meteor.call 'MuteAllUsers', getInSession("userId")
|
||||
|
@ -1,18 +1,19 @@
|
||||
<template name="usersList">
|
||||
<div id="{{id}}" {{visibility name}} class="component">
|
||||
<h3 class="title gradientBar"><span class="glyphicon glyphicon-user"></span> Participants: {{getMeetingSize}} Users</h3>
|
||||
<div id="user-contents">
|
||||
{{#Layout template="scrollWindow" id="publicUserScrollWindow"}}
|
||||
{{#contentFor region="scrollContents"}}
|
||||
{{#Layout template="moduleTable" tableClass="table table-hover" tbodyClass="user-entry"}}
|
||||
{{#contentFor region="Contents"}}
|
||||
{{#each getUsersInMeeting}}
|
||||
<tr>{{>userItem}}</tr>
|
||||
{{/each}}
|
||||
{{/contentFor}}
|
||||
{{/Layout}}
|
||||
{{/contentFor}}
|
||||
{{/Layout}}
|
||||
</div>
|
||||
</div>
|
||||
<div id="{{id}}" {{visibility name}} class="component">
|
||||
<h3 class="title gradientBar"><span class="glyphicon glyphicon-user"></span> Participants: {{getMeetingSize}} Users</h3>
|
||||
|
||||
<div id="user-contents">
|
||||
{{#Layout template="scrollWindow" id="publicUserScrollWindow"}}
|
||||
{{#contentFor region="scrollContents"}}
|
||||
{{#Layout template="moduleTable" tableClass="table table-hover" tbodyClass="user-entry"}}
|
||||
{{#contentFor region="Contents"}}
|
||||
{{#each getUsersInMeeting}}
|
||||
<tr>{{>userItem}}</tr>
|
||||
{{/each}}
|
||||
{{/contentFor}}
|
||||
{{/Layout}}
|
||||
{{/contentFor}}
|
||||
{{/Layout}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -88,11 +88,11 @@ class @WhiteboardPaperModel
|
||||
@raphaelObj.renderfix()
|
||||
|
||||
# initializing border around slide to cover up areas which shouldnt show
|
||||
@borders = {}
|
||||
for border in ['left', 'right', 'top', 'bottom']
|
||||
@borders[border] = @raphaelObj.rect(0, 0, 0, 0)
|
||||
@borders[border].attr("fill", "#ababab")
|
||||
@borders[border].attr( {stroke:"#ababab"} )
|
||||
# @borders = {}
|
||||
# for border in ['left', 'right', 'top', 'bottom']
|
||||
# @borders[border] = @raphaelObj.rect(0, 0, 0, 0)
|
||||
# @borders[border].attr("fill", "#ababab")
|
||||
# @borders[border].attr( {stroke:"#ababab"} )
|
||||
|
||||
@raphaelObj
|
||||
|
||||
@ -191,7 +191,7 @@ class @WhiteboardPaperModel
|
||||
for url of @slides
|
||||
if @slides.hasOwnProperty(url)
|
||||
@raphaelObj.getById(@slides[url]?.getId())?.remove()
|
||||
#@trigger('paper:image:removed', @slides[url].getId()) # TODO do we need this?
|
||||
@trigger('paper:image:removed', @slides[url].getId()) # Removes the previous image preventing images from being redrawn over each other repeatedly
|
||||
@slides = {}
|
||||
@current.slide = null
|
||||
|
||||
@ -765,7 +765,7 @@ class @WhiteboardPaperModel
|
||||
if url?.match(/http[s]?:/)
|
||||
url
|
||||
else
|
||||
console.log "the url did not match the expected format:#{url}"
|
||||
console.log "The url '#{url}'' did not match the expected format of: http/s"
|
||||
#globals.presentationServer + url
|
||||
|
||||
#Changes the currently displayed page/slide (if any) with this one
|
||||
|
@ -1,46 +0,0 @@
|
||||
Meteor.methods
|
||||
addChatToCollection: (meetingId, messageObject) ->
|
||||
# manually convert time from 1.408645053653E12 to 1408645053653 if necessary (this is the time_from that the Flash client outputs)
|
||||
messageObject.from_time = (messageObject.from_time).toString().split('.').join("").split("E")[0]
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
message:
|
||||
chat_type: messageObject.chat_type
|
||||
message: messageObject.message
|
||||
to_username: messageObject.to_username
|
||||
from_tz_offset: messageObject.from_tz_offset
|
||||
from_color: messageObject.from_color
|
||||
to_userid: messageObject.to_userid
|
||||
from_userid: messageObject.from_userid
|
||||
from_time: messageObject.from_time
|
||||
from_username: messageObject.from_username
|
||||
from_lang: messageObject.from_lang
|
||||
|
||||
id = Meteor.Chat.insert(entry)
|
||||
console.log "added chat id=[#{id}]:#{messageObject.message}. Chat.size is now
|
||||
#{Meteor.Chat.find({meetingId: meetingId}).count()}"
|
||||
|
||||
sendChatMessagetoServer: (meetingId, chatObject) ->
|
||||
# check if this is a private or a public chat message
|
||||
eventName = ->
|
||||
if chatObject.chat_type is "PRIVATE_CHAT"
|
||||
"send_private_chat_message_request"
|
||||
else "send_public_chat_message_request"
|
||||
|
||||
message =
|
||||
header :
|
||||
"timestamp": new Date().getTime()
|
||||
"name": eventName()
|
||||
payload:
|
||||
"message" : chatObject
|
||||
"meeting_id": meetingId
|
||||
"requester_id": chatObject.from_userid
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.chat, message)
|
||||
|
||||
deletePrivateChatMessages: (user1, user2) ->
|
||||
console.log "deleting chat conversation"
|
||||
Meteor.Chat.remove({ # find all and remove private messages between the 2 users
|
||||
'message.chat_type': 'PRIVATE_CHAT',
|
||||
$or: [{'message.from_userid': user1, 'message.to_userid': user2},{'message.from_userid': user2, 'message.to_userid': user1}]
|
||||
})
|
||||
|
@ -1,24 +0,0 @@
|
||||
Meteor.methods
|
||||
addMeetingToCollection: (meetingId, name, intendedForRecording, voiceConf, duration) ->
|
||||
#check if the meeting is already in the collection
|
||||
unless Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||
currentlyBeingRecorded = false # defaut value
|
||||
id = Meteor.Meetings.insert(
|
||||
meetingId: meetingId,
|
||||
meetingName: name,
|
||||
intendedForRecording: intendedForRecording,
|
||||
currentlyBeingRecorded: currentlyBeingRecorded,
|
||||
voiceConf: voiceConf,
|
||||
duration: duration)
|
||||
console.log "added meeting _id=[#{id}]:meetingId=[#{meetingId}]:name=[#{name}]:duration=[#{duration}]:voiceConf=[#{voiceConf}].
|
||||
Meetings.size is now #{Meteor.Meetings.find().count()}"
|
||||
|
||||
removeMeetingFromCollection: (meetingId) ->
|
||||
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||
if Meteor.Users.find({meetingId: meetingId}).count() isnt 0
|
||||
console.log "\n!!!!!removing a meeting which has active users in it!!!!\n"
|
||||
id = Meteor.Meetings.findOne({meetingId: meetingId})
|
||||
if id?
|
||||
Meteor.Meetings.remove(id._id)
|
||||
console.log "removed from Meetings:#{meetingId} now there are only
|
||||
#{Meteor.Meetings.find().count()} meetings running"
|
@ -1,26 +0,0 @@
|
||||
Meteor.methods
|
||||
addPresentationToCollection: (meetingId, presentationObject) ->
|
||||
#check if the presentation is already in the collection
|
||||
unless Meteor.Presentations.findOne({meetingId: meetingId, 'presentation.id': presentationObject.id})?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
presentation:
|
||||
id: presentationObject.id
|
||||
name: presentationObject.name
|
||||
current: presentationObject.current
|
||||
|
||||
pointer: #initially we have no data about the cursor
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
|
||||
id = Meteor.Presentations.insert(entry)
|
||||
console.log "added presentation id =[#{id}]:#{presentationObject.id} in #{meetingId}. Presentations.size is now
|
||||
#{Meteor.Presentations.find({meetingId: meetingId}).count()}"
|
||||
|
||||
removePresentationFromCollection: (meetingId, presentationId) ->
|
||||
if meetingId? and presentationId? and Meteor.Presentations.findOne({meetingId: meetingId, "presentation.id": presentationId})?
|
||||
id = Meteor.Presentations.findOne({meetingId: meetingId, "presentation.id": presentationId})
|
||||
if id?
|
||||
Meteor.Presentations.remove(id._id)
|
||||
console.log "----removed presentation[" + presentationId + "] from " + meetingId
|
||||
|
@ -1,79 +0,0 @@
|
||||
Meteor.methods
|
||||
addShapeToCollection: (meetingId, whiteboardId, shapeObject) ->
|
||||
console.log "shapeObject=" + JSON.stringify shapeObject
|
||||
if shapeObject?.shape_type is "text" and shapeObject.status is "textPublished"
|
||||
console.log "we are dealing with a text shape"
|
||||
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
whiteboardId: whiteboardId
|
||||
shape:
|
||||
type: shapeObject.shape.type
|
||||
textBoxHeight: shapeObject.shape.textBoxHeight
|
||||
backgroundColor: shapeObject.shape.backgroundColor
|
||||
fontColor: shapeObject.shape.fontColor
|
||||
status: shapeObject.shape.status
|
||||
dataPoints: shapeObject.shape.dataPoints
|
||||
x: shapeObject.shape.x
|
||||
textBoxWidth: shapeObject.shape.textBoxWidth
|
||||
whiteboardId: shapeObject.shape.whiteboardId
|
||||
fontSize: shapeObject.shape.fontSize
|
||||
id: shapeObject.shape.id
|
||||
y: shapeObject.shape.y
|
||||
calcedFontSize: shapeObject.shape.calcedFontSize
|
||||
text: shapeObject.shape.text
|
||||
background: shapeObject.shape.background
|
||||
|
||||
id = Meteor.Shapes.insert(entry)
|
||||
numShapesOnSlide = Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch().length
|
||||
console.log "added textShape id =[#{id}]:#{shapeObject.id} in #{meetingId} || now there are #{numShapesOnSlide} shapes on the slide"
|
||||
|
||||
else
|
||||
# the mouse button was released - the drawing is complete
|
||||
# TODO: pencil messages currently don't send draw_end and are labeled all as DRAW_START
|
||||
if shapeObject?.status is "DRAW_END" or (shapeObject?.status is "DRAW_START" and shapeObject?.shape_type is "pencil")
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
whiteboardId: whiteboardId
|
||||
shape:
|
||||
wb_id: shapeObject.wb_id
|
||||
shape_type: shapeObject.shape_type
|
||||
status: shapeObject.status
|
||||
id: shapeObject.id
|
||||
shape:
|
||||
type: shapeObject.shape.type
|
||||
status: shapeObject.shape.status
|
||||
points: shapeObject.shape.points
|
||||
whiteboardId: shapeObject.shape.whiteboardId
|
||||
id: shapeObject.shape.id
|
||||
square: shapeObject.shape.square
|
||||
transparency: shapeObject.shape.transparency
|
||||
thickness: shapeObject.shape.thickness
|
||||
color: shapeObject.shape.color
|
||||
|
||||
id = Meteor.Shapes.insert(entry)
|
||||
numShapesOnSlide = Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch().length
|
||||
console.log "added shape id =[#{id}]:#{shapeObject.id} in #{meetingId} || now there are #{numShapesOnSlide} shapes on the slide"
|
||||
|
||||
removeAllShapesFromSlide: (meetingId, whiteboardId) ->
|
||||
console.log "removeAllShapesFromSlide__" + whiteboardId
|
||||
if meetingId? and whiteboardId? and Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId})?
|
||||
shapesOnSlide = Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch()
|
||||
console.log "number of shapes:" + shapesOnSlide.length
|
||||
for s in shapesOnSlide
|
||||
console.log "shape=" + s.shape.id
|
||||
id = Meteor.Shapes.findOne({meetingId: meetingId, whiteboardId: whiteboardId, "shape.id": s.shape.id})
|
||||
if id?
|
||||
Meteor.Shapes.remove(id._id)
|
||||
console.log "----removed shape[" + s.shape.id + "] from " + whiteboardId
|
||||
console.log "remaining shapes on the slide:" + Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch().length
|
||||
|
||||
removeShapeFromSlide: (meetingId, whiteboardId, shapeId) ->
|
||||
shapeToRemove = Meteor.Shapes.findOne({meetingId: meetingId, whiteboardId: whiteboardId, "shape.id": shapeId})
|
||||
if meetingId? and whiteboardId? and shapeId? and shapeToRemove?
|
||||
Meteor.Shapes.remove(shapeToRemove._id)
|
||||
console.log "----removed shape[" + shapeId + "] from " + whiteboardId
|
||||
console.log "remaining shapes on the slide:" + Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).count()
|
||||
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
Meteor.methods
|
||||
addSlideToCollection: (meetingId, presentationId, slideObject) ->
|
||||
unless Meteor.Slides.findOne({meetingId: meetingId, "slide.id": slideObject.id})?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
presentationId: presentationId
|
||||
slide:
|
||||
height_ratio: slideObject.height_ratio
|
||||
y_offset: slideObject.y_offset
|
||||
num: slideObject.num
|
||||
x_offset: slideObject.x_offset
|
||||
current: slideObject.current
|
||||
png_uri: slideObject.png_uri
|
||||
txt_uri: slideObject.txt_uri
|
||||
id: slideObject.id
|
||||
width_ratio: slideObject.width_ratio
|
||||
swf_uri: slideObject.swf_uri
|
||||
thumb_uri: slideObject.thumb_uri
|
||||
|
||||
id = Meteor.Slides.insert(entry)
|
||||
console.log "added slide id =[#{id}]:#{slideObject.id} in #{meetingId}. Now there are
|
||||
#{Meteor.Slides.find({meetingId: meetingId}).count()} slides in the meeting"
|
||||
|
||||
removeSlideFromCollection: (meetingId, slideId) ->
|
||||
if meetingId? and slideId? and Meteor.Slides.findOne({meetingId: meetingId, "slide.id": slideId})?
|
||||
id = Meteor.Slides.findOne({meetingId: meetingId, "slide.id": slideId})
|
||||
if id?
|
||||
Meteor.Slides.remove(id._id)
|
||||
console.log "----removed slide[" + slideId + "] from " + meetingId
|
||||
|
||||
displayThisSlide: (meetingId, newSlideId, slideObject) ->
|
||||
presentationId = newSlideId.split("/")[0] # grab the presentationId part of the slideId
|
||||
# change current to false for the old slide
|
||||
Meteor.Slides.update({presentationId: presentationId, "slide.current": true}, {$set: {"slide.current": false}})
|
||||
|
||||
# for the new slide: remove the version which came with presentation_shared_message from the Collection
|
||||
# to avoid using old data (this message contains everything we need for the new slide)
|
||||
Meteor.call("removeSlideFromCollection", meetingId, newSlideId)
|
||||
# add the new slide to the collection
|
||||
Meteor.call("addSlideToCollection", meetingId, presentationId, slideObject)
|
@ -1,173 +0,0 @@
|
||||
Meteor.methods
|
||||
addUserToCollection: (meetingId, user) ->
|
||||
userId = user.userid
|
||||
#check if the user is already in the meeting
|
||||
unless Meteor.Users.findOne({userId:userId, meetingId: meetingId})?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
userId: userId
|
||||
user:
|
||||
userid: user.userid
|
||||
presenter: user.presenter
|
||||
name: user.name
|
||||
phone_user: user.phone_user
|
||||
raise_hand: user.raise_hand
|
||||
has_stream: user.has_stream
|
||||
role: user.role
|
||||
listenOnly: user.listenOnly
|
||||
extern_userid: user.extern_userid
|
||||
permissions: user.permissions
|
||||
locked: user.locked
|
||||
time_of_joining: user.timeOfJoining
|
||||
voiceUser:
|
||||
web_userid: user.voiceUser.web_userid
|
||||
callernum: user.voiceUser.callernum
|
||||
userid: user.voiceUser.userid
|
||||
talking: user.voiceUser.talking
|
||||
joined: user.voiceUser.joined
|
||||
callername: user.voiceUser.callername
|
||||
locked: user.voiceUser.locked
|
||||
muted: user.voiceUser.muted
|
||||
webcam_stream: user.webcam_stream
|
||||
|
||||
id = Meteor.Users.insert(entry)
|
||||
console.log "added user id=[#{id}]:#{user.name}. Users.size is now #{Meteor.Users.find({meetingId: meetingId}).count()}"
|
||||
|
||||
removeUserFromCollection: (meetingId, userId) ->
|
||||
if meetingId? and userId? and Meteor.Users.findOne({meetingId: meetingId, userId: userId})?
|
||||
id = Meteor.Users.findOne({meetingId: meetingId, userId: userId})
|
||||
if id?
|
||||
Meteor.Users.remove(id._id)
|
||||
console.log "----removed user[" + userId + "] from " + meetingId
|
||||
|
||||
#
|
||||
# Voice
|
||||
userShareAudio: (meetingId, userId) ->
|
||||
if meetingId? and userId?
|
||||
Meteor.call('updateVoiceUser',meetingId, {web_userid: userId, talking:false, joined: true, muted:false})
|
||||
#TODO should we also send a message to bbb-apps about it?
|
||||
|
||||
userStopAudio: (meetingId, userId) ->
|
||||
console.log "publishing a user left voice request for #{userId} in #{meetingId}"
|
||||
message =
|
||||
"payload":
|
||||
"userid": userId
|
||||
"meeting_id": meetingId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_left_voice_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
if meetingId? and userId?
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.voice, message)
|
||||
Meteor.call('updateVoiceUser',meetingId, {web_userid: userId, talking:false, joined: false, muted:false})
|
||||
else
|
||||
console.log "did not have enough information to send a mute_user_request"
|
||||
|
||||
#update a voiceUser - a helper method
|
||||
updateVoiceUser: (meetingId, voiceUserObject) ->
|
||||
console.log "I am updating the voiceUserObject with the following: " + JSON.stringify voiceUserObject
|
||||
u = Meteor.Users.findOne({userId: voiceUserObject?.web_userid, meetingId: meetingId})
|
||||
if u?
|
||||
if voiceUserObject?.talking?
|
||||
Meteor.Users.update({_id:u._id}, {$set: {'user.voiceUser.talking':voiceUserObject?.talking}})# talking
|
||||
if voiceUserObject?.joined?
|
||||
Meteor.Users.update({_id:u._id}, {$set: {'user.voiceUser.joined':voiceUserObject?.joined}})# joined
|
||||
if voiceUserObject?.locked?
|
||||
Meteor.Users.update({_id:u._id}, {$set: {'user.voiceUser.locked':voiceUserObject?.locked}})# locked
|
||||
if voiceUserObject?.muted?
|
||||
Meteor.Users.update({_id:u._id}, {$set: {'user.voiceUser.muted':voiceUserObject?.muted}})# muted
|
||||
else
|
||||
console.log "ERROR! did not find such voiceUser!"
|
||||
|
||||
publishMuteRequest: (meetingId, userId, requesterId, mutedBoolean) ->
|
||||
console.log "publishing a user mute #{mutedBoolean} request for #{userId}"
|
||||
message =
|
||||
"payload":
|
||||
"userid": userId
|
||||
"meeting_id": meetingId
|
||||
"mute": mutedBoolean
|
||||
"requester_id": requesterId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "mute_user_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
if meetingId? and userId? and requesterId?
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.voice, message)
|
||||
# modify the collection
|
||||
Meteor.Users.update({userId:userId, meetingId: meetingId}, {$set:{'user.voiceUser.talking':false}})
|
||||
numChanged = Meteor.Users.update({userId:userId, meetingId: meetingId}, {$set:{'user.voiceUser.muted':mutedBoolean}})
|
||||
if numChanged isnt 1
|
||||
console.log "\n\nSomething went wrong!! We were supposed to mute/unmute 1 user!!\n\n"
|
||||
else
|
||||
console.log "did not have enough information to send a mute_user_request"
|
||||
|
||||
# Raise & Lower hand
|
||||
userLowerHand: (meetingId, userId, loweredBy) ->
|
||||
console.log "publishing a userLowerHand event: #{userId}--by=#{loweredBy}"
|
||||
|
||||
if meetingId? and userId? and loweredBy?
|
||||
message =
|
||||
"payload":
|
||||
"userid": userId
|
||||
"meeting_id": meetingId
|
||||
"raise_hand": false
|
||||
"lowered_by": loweredBy
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_lowered_hand_message"
|
||||
"version": "0.0.1"
|
||||
|
||||
#publish to pubsub
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.users, message)
|
||||
#update Users collection
|
||||
Meteor.Users.update({userId:userId, meetingId: meetingId}, {$set: {'user.raise_hand': false}})
|
||||
|
||||
userRaiseHand: (meetingId, userId) ->
|
||||
console.log "publishing a userRaiseHand event: #{userId}"
|
||||
|
||||
if meetingId? and userId?
|
||||
message =
|
||||
"payload":
|
||||
"userid": userId
|
||||
"meeting_id": meetingId
|
||||
"raise_hand": true
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_raised_hand_message"
|
||||
"version": "0.0.1"
|
||||
|
||||
#publish to pubsub
|
||||
Meteor.call('publish',Meteor.config.redis.channels.toBBBApps.users, message)
|
||||
#update Users collection
|
||||
Meteor.Users.update({userId:userId, meetingId: meetingId}, {$set: {'user.raise_hand': true}})
|
||||
|
||||
userLogout: (meetingId, userId) ->
|
||||
console.log "a user is logging out:" + userId
|
||||
#remove from the collection
|
||||
Meteor.call("removeUserFromCollection", meetingId, userId)
|
||||
#dispatch a message to redis
|
||||
Meteor.call('sendUserLeavingRequest', meetingId, userId)
|
||||
|
||||
userKick: (meetingId, userId) ->
|
||||
console.log "#{userId} is being kicked"
|
||||
#remove from the collection
|
||||
Meteor.call("removeUserFromCollection", meetingId, userId)
|
||||
#dispatch a message to redis
|
||||
Meteor.call('sendUserLeavingRequest', meetingId, userId)
|
||||
|
||||
sendUserLeavingRequest: (meetingId, userId) ->
|
||||
console.log "\n\n sending a user_leaving_request for #{meetingId}:#{userId}"
|
||||
message =
|
||||
"payload":
|
||||
"meeting_id": meetingId
|
||||
"userid": userId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_leaving_request"
|
||||
"version": "0.0.1"
|
||||
if userId? and meetingId?
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.users, message)
|
||||
else
|
||||
console.log "did not have enough information to send a user_leaving_request"
|
@ -14,10 +14,16 @@
|
||||
Meteor.subscribe 'slides', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'meetings', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'presentations', getInSession('meetingId'), ->
|
||||
|
||||
# Obtain user info here. for testing. should be moved somewhere else later
|
||||
Meteor.call "getMyInfo", getInSession("userId"), (error, result) ->
|
||||
setInSession("DBID", result.DBID)
|
||||
setInSession("userName", result.name)
|
||||
|
||||
self.redirect('/')
|
||||
|
||||
onBeforeAction: ()->
|
||||
url = location.href
|
||||
url = location.href
|
||||
console.log "\n\nurl=#{url}\n\n"
|
||||
#extract the meeting_id, user_id, auth_token, etc from the uri
|
||||
if url.indexOf("meeting_id") > -1 # if the URL is /meeting_id=...&...
|
||||
@ -33,17 +39,9 @@
|
||||
console.log "authToken=" + authToken
|
||||
|
||||
if meetingId? and userId? and authToken?
|
||||
# Here we need to check whether there is already a user using userId inside meetingId, if there is don't let this user log in, it is a duplicate
|
||||
###
|
||||
if Meteor.call("validateUserId", meetingId, userId)
|
||||
continue
|
||||
else
|
||||
kick user out
|
||||
###
|
||||
|
||||
Meteor.call("validateAuthToken", meetingId, userId, authToken)
|
||||
Meteor.call('sendMeetingInfoToClient', meetingId, userId)
|
||||
else
|
||||
else
|
||||
console.log "unable to extract from the URL some of {meetingId, userId, authToken}"
|
||||
else
|
||||
console.log "unable to extract the required information for the meeting from the URL"
|
||||
@ -51,20 +49,17 @@
|
||||
path: "/"
|
||||
onBeforeAction: ->
|
||||
self = @
|
||||
# Have to check on the server whether the credentials the user has are valid on db, without being able to spam requests for credentials
|
||||
Meteor.subscribe 'users', getInSession('meetingId'), -> # callback for after users have been loaded on client
|
||||
if not validateCredentials() # Don't let user in if they are not valid
|
||||
self.redirect("logout")
|
||||
else
|
||||
Meteor.subscribe 'chat', getInSession('meetingId'), getInSession("userId"), ->
|
||||
Meteor.subscribe 'shapes', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'slides', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'meetings', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'presentations', getInSession('meetingId')
|
||||
Meteor.subscribe 'chat', getInSession('meetingId'), getInSession("userId"), ->
|
||||
Meteor.subscribe 'shapes', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'slides', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'meetings', getInSession('meetingId'), ->
|
||||
Meteor.subscribe 'presentations', getInSession('meetingId'), ->
|
||||
# Obtain user info here. for testing. should be moved somewhere else later
|
||||
Meteor.call "getMyInfo", getInSession("userId"), (error, result) ->
|
||||
setInSession("DBID", result.DBID)
|
||||
setInSession("userName", result.name)
|
||||
|
||||
@route "logout",
|
||||
path: "logout"
|
||||
|
||||
@validateCredentials = ->
|
||||
u = Meteor.Users.findOne({"userId":getInSession("userId")})
|
||||
# return whether they are a valid user and still have credentials in the database
|
||||
u? and u.meetingId? and u.user?.extern_userid and u.user?.userid #and (1 is 2) # makes validation fail
|
||||
|
87
labs/meteor-client/app/server/collection_methods/chat.coffee
Executable file
87
labs/meteor-client/app/server/collection_methods/chat.coffee
Executable file
@ -0,0 +1,87 @@
|
||||
Meteor.methods
|
||||
sendChatMessagetoServer: (meetingId, chatObject, requesterUserId) ->
|
||||
# inside the chatObject, they store their _id as the sender
|
||||
# and they pass their userId to this method as a param
|
||||
transformedChatObject = chatObject
|
||||
|
||||
console.log "requesterUserId: #{requesterUserId} | from_userid: #{transformedChatObject.from_userid}"
|
||||
requester = Meteor.Users.findOne({_id: transformedChatObject.from_userid, userId: requesterUserId})
|
||||
forPublic = transformedChatObject.to_userid is 'public_chat_userid'
|
||||
|
||||
if requester? # User exists, and is valid
|
||||
console.log "requester exists"
|
||||
# check if this is a private or a public chat message
|
||||
eventName = ->
|
||||
if transformedChatObject.chat_type is "PRIVATE_CHAT"
|
||||
"send_private_chat_message_request"
|
||||
else "send_public_chat_message_request"
|
||||
|
||||
recipient = Meteor.Users.findOne(_id: transformedChatObject.to_userid)
|
||||
if recipient? or forPublic
|
||||
|
||||
# translate _ids to userIds for flash
|
||||
transformedChatObject.from_userid = requester.userId
|
||||
transformedChatObject.to_userid = if forPublic then 'public_chat_userid' else recipient.userId
|
||||
|
||||
message =
|
||||
header :
|
||||
"timestamp": new Date().getTime()
|
||||
"name": eventName()
|
||||
payload:
|
||||
"message" : transformedChatObject
|
||||
"meeting_id": meetingId
|
||||
"requester_id": transformedChatObject.from_userid
|
||||
#
|
||||
console.log JSON.stringify transformedChatObject
|
||||
publish Meteor.config.redis.channels.toBBBApps.chat, message
|
||||
#
|
||||
else
|
||||
console.log "requester no exists"
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
@deletePrivateChatMessages = (user1Id, user2Id) ->
|
||||
Meteor.Chat.remove({ # find all and remove private messages between the 2 users
|
||||
'message.chat_type': 'PRIVATE_CHAT',
|
||||
$or: [{'message.from_userid': user1Id, 'message.to_userid': user2Id},{'message.from_userid': user2Id, 'message.to_userid': user1Id}]
|
||||
})
|
||||
# send a message to redis out about deleting conversation between these 2 users
|
||||
#
|
||||
|
||||
@addChatToCollection = (meetingId, messageObject) ->
|
||||
console.log "-------------addChatToCollection---------------------"
|
||||
transformedChatObject = messageObject
|
||||
|
||||
# manually convert time from 1.408645053653E12 to 1408645053653 if necessary (this is the time_from that the Flash client outputs)
|
||||
transformedChatObject.from_time = (transformedChatObject.from_time).toString().split('.').join("").split("E")[0]
|
||||
|
||||
fromUser = Meteor.Users.findOne({userId: transformedChatObject.from_userid})
|
||||
toUser = Meteor.Users.findOne({userId: transformedChatObject.to_userid})
|
||||
forPublic = transformedChatObject.to_userid is 'public_chat_userid'
|
||||
|
||||
if (fromUser? and toUser?) or forPublic
|
||||
# translate ids from flash to html5
|
||||
transformedChatObject.from_userid = fromUser._id
|
||||
transformedChatObject.to_userid = if forPublic then 'public_chat_userid' else toUser._id
|
||||
|
||||
if transformedChatObject.from_userid? and transformedChatObject.to_userid?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
message:
|
||||
chat_type: transformedChatObject.chat_type
|
||||
message: transformedChatObject.message
|
||||
to_username: transformedChatObject.to_username
|
||||
from_tz_offset: transformedChatObject.from_tz_offset
|
||||
from_color: transformedChatObject.from_color
|
||||
to_userid: transformedChatObject.to_userid
|
||||
from_userid: transformedChatObject.from_userid
|
||||
from_time: transformedChatObject.from_time
|
||||
from_username: transformedChatObject.from_username
|
||||
from_lang: transformedChatObject.from_lang
|
||||
|
||||
id = Meteor.Chat.insert(entry)
|
||||
console.log "added chat id=[#{id}]:#{transformedChatObject.message}. Chat.size is now #{Meteor.Chat.find({meetingId: meetingId}).count()}"
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# end Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
27
labs/meteor-client/app/server/collection_methods/meetings.coffee
Executable file
27
labs/meteor-client/app/server/collection_methods/meetings.coffee
Executable file
@ -0,0 +1,27 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
@addMeetingToCollection = (meetingId, name, intendedForRecording, voiceConf, duration) ->
|
||||
#check if the meeting is already in the collection
|
||||
unless Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||
currentlyBeingRecorded = false # defaut value
|
||||
id = Meteor.Meetings.insert(
|
||||
meetingId: meetingId,
|
||||
meetingName: name,
|
||||
intendedForRecording: intendedForRecording,
|
||||
currentlyBeingRecorded: currentlyBeingRecorded,
|
||||
voiceConf: voiceConf,
|
||||
duration: duration)
|
||||
console.log "added meeting _id=[#{id}]:meetingId=[#{meetingId}]:name=[#{name}]:duration=[#{duration}]:voiceConf=[#{voiceConf}].Meetings.size is now #{Meteor.Meetings.find().count()}"
|
||||
|
||||
@removeMeetingFromCollection = (meetingId) ->
|
||||
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||
if Meteor.Users.find({meetingId: meetingId}).count() isnt 0
|
||||
console.log "\n!!!!!removing a meeting which has active users in it!!!!\n"
|
||||
id = Meteor.Meetings.findOne({meetingId: meetingId})
|
||||
if id?
|
||||
Meteor.Meetings.remove(id._id)
|
||||
console.log "removed from Meetings:#{meetingId} now there are only #{Meteor.Meetings.find().count()} meetings running"
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# end Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
29
labs/meteor-client/app/server/collection_methods/presentations.coffee
Executable file
29
labs/meteor-client/app/server/collection_methods/presentations.coffee
Executable file
@ -0,0 +1,29 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
@addPresentationToCollection = (meetingId, presentationObject) ->
|
||||
#check if the presentation is already in the collection
|
||||
unless Meteor.Presentations.findOne({meetingId: meetingId, 'presentation.id': presentationObject.id})?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
presentation:
|
||||
id: presentationObject.id
|
||||
name: presentationObject.name
|
||||
current: presentationObject.current
|
||||
|
||||
pointer: #initially we have no data about the cursor
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
|
||||
id = Meteor.Presentations.insert(entry)
|
||||
console.log "presentation added id =[#{id}]:#{presentationObject.id} in #{meetingId}. Presentations.size is now #{Meteor.Presentations.find({meetingId: meetingId}).count()}"
|
||||
|
||||
@removePresentationFromCollection = (meetingId, presentationId) ->
|
||||
if meetingId? and presentationId? and Meteor.Presentations.findOne({meetingId: meetingId, "presentation.id": presentationId})?
|
||||
id = Meteor.Presentations.findOne({meetingId: meetingId, "presentation.id": presentationId})
|
||||
if id?
|
||||
Meteor.Presentations.remove(id._id)
|
||||
console.log "----removed presentation[" + presentationId + "] from " + meetingId
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# end Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
81
labs/meteor-client/app/server/collection_methods/shapes.coffee
Executable file
81
labs/meteor-client/app/server/collection_methods/shapes.coffee
Executable file
@ -0,0 +1,81 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
@addShapeToCollection = (meetingId, whiteboardId, shapeObject) ->
|
||||
console.log "shapeObject=" + JSON.stringify shapeObject
|
||||
if shapeObject?.shape_type is "text" and shapeObject.status is "textPublished"
|
||||
console.log "we are dealing with a text shape"
|
||||
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
whiteboardId: whiteboardId
|
||||
shape:
|
||||
type: shapeObject.shape.type
|
||||
textBoxHeight: shapeObject.shape.textBoxHeight
|
||||
backgroundColor: shapeObject.shape.backgroundColor
|
||||
fontColor: shapeObject.shape.fontColor
|
||||
status: shapeObject.shape.status
|
||||
dataPoints: shapeObject.shape.dataPoints
|
||||
x: shapeObject.shape.x
|
||||
textBoxWidth: shapeObject.shape.textBoxWidth
|
||||
whiteboardId: shapeObject.shape.whiteboardId
|
||||
fontSize: shapeObject.shape.fontSize
|
||||
id: shapeObject.shape.id
|
||||
y: shapeObject.shape.y
|
||||
calcedFontSize: shapeObject.shape.calcedFontSize
|
||||
text: shapeObject.shape.text
|
||||
background: shapeObject.shape.background
|
||||
|
||||
id = Meteor.Shapes.insert(entry)
|
||||
numShapesOnSlide = Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch().length
|
||||
console.log "added textShape id =[#{id}]:#{shapeObject.id} in #{meetingId} || now there are #{numShapesOnSlide} shapes on the slide"
|
||||
|
||||
else
|
||||
# the mouse button was released - the drawing is complete
|
||||
# TODO: pencil messages currently don't send draw_end and are labeled all as DRAW_START
|
||||
if shapeObject?.status is "DRAW_END" or (shapeObject?.status is "DRAW_START" and shapeObject?.shape_type is "pencil")
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
whiteboardId: whiteboardId
|
||||
shape:
|
||||
wb_id: shapeObject.wb_id
|
||||
shape_type: shapeObject.shape_type
|
||||
status: shapeObject.status
|
||||
id: shapeObject.id
|
||||
shape:
|
||||
type: shapeObject.shape.type
|
||||
status: shapeObject.shape.status
|
||||
points: shapeObject.shape.points
|
||||
whiteboardId: shapeObject.shape.whiteboardId
|
||||
id: shapeObject.shape.id
|
||||
square: shapeObject.shape.square
|
||||
transparency: shapeObject.shape.transparency
|
||||
thickness: shapeObject.shape.thickness
|
||||
color: shapeObject.shape.color
|
||||
|
||||
id = Meteor.Shapes.insert(entry)
|
||||
numShapesOnSlide = Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch().length
|
||||
console.log "added shape id =[#{id}]:#{shapeObject.id} in #{meetingId} || now there are #{numShapesOnSlide} shapes on the slide"
|
||||
|
||||
@removeAllShapesFromSlide = (meetingId, whiteboardId) ->
|
||||
console.log "removeAllShapesFromSlide__" + whiteboardId
|
||||
if meetingId? and whiteboardId? and Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId})?
|
||||
shapesOnSlide = Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch()
|
||||
console.log "number of shapes:" + shapesOnSlide.length
|
||||
for s in shapesOnSlide
|
||||
console.log "shape=" + s.shape.id
|
||||
id = Meteor.Shapes.findOne({meetingId: meetingId, whiteboardId: whiteboardId, "shape.id": s.shape.id})
|
||||
if id?
|
||||
Meteor.Shapes.remove(id._id)
|
||||
console.log "----removed shape[" + s.shape.id + "] from " + whiteboardId
|
||||
console.log "remaining shapes on the slide:" + Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).fetch().length
|
||||
|
||||
@removeShapeFromSlide = (meetingId, whiteboardId, shapeId) ->
|
||||
shapeToRemove = Meteor.Shapes.findOne({meetingId: meetingId, whiteboardId: whiteboardId, "shape.id": shapeId})
|
||||
if meetingId? and whiteboardId? and shapeId? and shapeToRemove?
|
||||
Meteor.Shapes.remove(shapeToRemove._id)
|
||||
console.log "----removed shape[" + shapeId + "] from " + whiteboardId
|
||||
console.log "remaining shapes on the slide:" + Meteor.Shapes.find({meetingId: meetingId, whiteboardId: whiteboardId}).count()
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# end Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
44
labs/meteor-client/app/server/collection_methods/slides.coffee
Executable file
44
labs/meteor-client/app/server/collection_methods/slides.coffee
Executable file
@ -0,0 +1,44 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
@displayThisSlide = (meetingId, newSlideId, slideObject) ->
|
||||
presentationId = newSlideId.split("/")[0] # grab the presentationId part of the slideId
|
||||
# change current to false for the old slide
|
||||
Meteor.Slides.update({presentationId: presentationId, "slide.current": true}, {$set: {"slide.current": false}})
|
||||
# for the new slide: remove the version which came with presentation_shared_message from the Collection
|
||||
# to avoid using old data (this message contains everything we need for the new slide)
|
||||
Meteor.call("removeSlideFromCollection", meetingId, newSlideId)
|
||||
# add the new slide to the collection
|
||||
Meteor.call("addSlideToCollection", meetingId, presentationId, slideObject)
|
||||
|
||||
|
||||
@addSlideToCollection = (meetingId, presentationId, slideObject) ->
|
||||
unless Meteor.Slides.findOne({meetingId: meetingId, "slide.id": slideObject.id})?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
presentationId: presentationId
|
||||
slide:
|
||||
height_ratio: slideObject.height_ratio
|
||||
y_offset: slideObject.y_offset
|
||||
num: slideObject.num
|
||||
x_offset: slideObject.x_offset
|
||||
current: slideObject.current
|
||||
png_uri: slideObject.png_uri
|
||||
txt_uri: slideObject.txt_uri
|
||||
id: slideObject.id
|
||||
width_ratio: slideObject.width_ratio
|
||||
swf_uri: slideObject.swf_uri
|
||||
thumb_uri: slideObject.thumb_uri
|
||||
|
||||
id = Meteor.Slides.insert(entry)
|
||||
console.log "added slide id =[#{id}]:#{slideObject.id} in #{meetingId}. Now there are #{Meteor.Slides.find({meetingId: meetingId}).count()} slides in the meeting"
|
||||
|
||||
@removeSlideFromCollection = (meetingId, slideId) ->
|
||||
if meetingId? and slideId? and Meteor.Slides.findOne({meetingId: meetingId, "slide.id": slideId})?
|
||||
id = Meteor.Slides.findOne({meetingId: meetingId, "slide.id": slideId})
|
||||
if id?
|
||||
Meteor.Slides.remove(id._id)
|
||||
console.log "----removed slide[" + slideId + "] from " + meetingId
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# end Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
235
labs/meteor-client/app/server/collection_methods/users.coffee
Executable file
235
labs/meteor-client/app/server/collection_methods/users.coffee
Executable file
@ -0,0 +1,235 @@
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Public methods on server
|
||||
# All these method must first authenticate the user before it calls the private function counterpart below
|
||||
# which sends the request to bbbApps. If the method is modifying the media the current user is sharing,
|
||||
# you should perform the request before sending the request to bbbApps. This allows the user request to be performed
|
||||
# immediately, since they do not require permission for things such as muting themsevles.
|
||||
# --------------------------------------------------------------------------------------------
|
||||
Meteor.methods
|
||||
# I did not simply loop through all users and call the 'publishMuteRequest' because that function
|
||||
# always validates the credentials of the requester. This is a waste of resources when applying it to every user.
|
||||
# We can validate the muter first, then mute all users individually
|
||||
# Perhaps there should be a way to send a mute request to bbbApps for several users, instead of an individual request for each user (bandwidth)
|
||||
MuteAllUsers: (meetingId, requesterUserId, requester_id) ->
|
||||
console.log "MuteAllUsers server method"
|
||||
muter = Meteor.Users.findOne({'meetingId': meetingId, 'userId': requesterUserId, _id: requester_id})
|
||||
|
||||
if muter?.presenter? and muter.presenter # or if they are a moderator?
|
||||
users = Meteor.Users.find({}).fetch()
|
||||
|
||||
for mutee in users
|
||||
# check if user isnt muted, then continue. If they are already muted you can skip them
|
||||
message =
|
||||
"payload":
|
||||
"userid": mutee.userId
|
||||
"meeting_id": meetingId
|
||||
"mute": mutedBoolean
|
||||
"requester_id": muter.userId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "mute_user_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
publish Meteor.config.redis.channels.toBBBApps.voice, message
|
||||
updateVoiceUser {'user_id': mutee._id, talking:false, muted:true}
|
||||
|
||||
userShareAudio: (meetingId, userId, user_id) ->
|
||||
updateVoiceUser {'user_id': user_id, 'talking':false, 'joined': true, 'muted':false}
|
||||
#TODO we need to send a message to bbb-apps about it
|
||||
|
||||
userStopAudio: (meetingId, userId, user_id, requesterUserId, requester_id) ->
|
||||
console.log "publishing a user left voice request for #{userId} in #{meetingId}"
|
||||
user = Meteor.Users.findOne({'meetingId': meetingId, 'userId': userId, '_id': user_id})
|
||||
requester = Meteor.Users.findOne({'meetingId': meetingId, 'userId': requesterUserId, '_id': requester_id})
|
||||
if user? and requester? and ((user._id is requester._id) or requester.presenter)
|
||||
message =
|
||||
"payload":
|
||||
"userid": user.userId
|
||||
"meeting_id": user.meetingId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_left_voice_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
publish Meteor.config.redis.channels.toBBBApps.voice, message
|
||||
updateVoiceUser {'user_id': user_id, talking:false, joined: true, muted:false}
|
||||
else
|
||||
console.log "did not have enough information to send a mute_user_request"
|
||||
|
||||
# Verifies muter exists, provided proper credentials, and has permission to mute the user
|
||||
publishMuteRequest: (meetingId, mutee_id, requesterUserId, requester_id, mutedBoolean) ->
|
||||
console.log "publishing a user mute #{mutedBoolean} request for #{mutee_id}"
|
||||
|
||||
mutee = Meteor.Users.findOne({'meetingId': meetingId, _id: mutee_id})
|
||||
muter = Meteor.Users.findOne({'meetingId': meetingId, 'userId': requesterUserId, _id: requester_id})
|
||||
if mutee? and muter?
|
||||
message =
|
||||
"payload":
|
||||
"userid": mutee.userId
|
||||
"meeting_id": meetingId
|
||||
"mute": mutedBoolean
|
||||
"requester_id": muter.userId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "mute_user_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
publish Meteor.config.redis.channels.toBBBApps.voice, message
|
||||
updateVoiceUser {'user_id': mutee._id, talking:false, muted:true}
|
||||
#
|
||||
else
|
||||
console.log "did not have enough information to send a mute_user_request"
|
||||
|
||||
# meetingId: the meetingId which both users are in
|
||||
# user_id: the _id of the user to have their hand lowered
|
||||
# loweredByUserId: userId of person lowering
|
||||
# loweredBy_id: _id of person lowering
|
||||
userLowerHand: (meetingId, toLowerUser_Id, loweredByUserId, loweredBy_id) ->
|
||||
requester = Meteor.Users.findOne({'meetingId': meetingId, 'userId': loweredByUserId, '_id': loweredBy_id})
|
||||
if requester?
|
||||
# Allow if person lowering the hand is the presenter, or they're lowering their own hand
|
||||
unless requester.user.presenter or loweredBy_id is toLowerUser_Id or requester.role is "MODERATOR"
|
||||
return
|
||||
|
||||
console.log "publishing a userLowerHand event: #{userId}--by=#{requester._id}"
|
||||
toLower = Meteor.Users.findOne({'meetingId': meetingId, '_id': toLowerUser_Id})
|
||||
if toLower?
|
||||
message =
|
||||
"payload":
|
||||
"userid": toLower.userId
|
||||
"meeting_id": meetingId
|
||||
"raise_hand": false
|
||||
"lowered_by": loweredByUserId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_lowered_hand_message"
|
||||
"version": "0.0.1"
|
||||
|
||||
# publish to pubsub
|
||||
publish Meteor.config.redis.channels.toBBBApps.users, message
|
||||
|
||||
# meetingId: the meetingId which both users are in
|
||||
# user_id: the _id of the user to have their hand raised
|
||||
# loweredByUserId: userId of person raising
|
||||
# loweredBy_id: _id of person raising
|
||||
userRaiseHand: (meetingId, user_id, raisedByUserId, raisedBy_id) ->
|
||||
requester = Meteor.Users.findOne({'meetingId': meetingId, 'userId': raisedByUserId, '_id': raisedBy_id})
|
||||
if requester?
|
||||
# Allow if person raising the hand is the presenter, or they're raising their own hand
|
||||
unless requester.user.presenter or raisedBy_id is user_id or requester.role is "MODERATOR"
|
||||
return
|
||||
|
||||
console.log "publishing a userRaiseHand event: #{userId}--by=#{requester._id}"
|
||||
toRaise = Meteor.Users.findOne({'meetingId': meetingId, '_id': user_id})
|
||||
if toRaise?
|
||||
message =
|
||||
"payload":
|
||||
"userid": toRaise.userId
|
||||
"meeting_id": meetingId
|
||||
"raise_hand": true
|
||||
"raised_by": raisedByUserId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_raised_hand_message"
|
||||
"version": "0.0.1"
|
||||
|
||||
# publish to pubsub
|
||||
publish Meteor.config.redis.channels.toBBBApps.users, message
|
||||
|
||||
userLogout: (meetingId, userId, user_id) ->
|
||||
console.log "a user is logging out:" + userId
|
||||
u = Meteor.Users.findOne({meetingId: meetingId, _id: user_id, userId: userId})
|
||||
if u?
|
||||
#remove from the collection and dispatch a message to redis
|
||||
removeUserFromMeeting meetingId, u.userId, u.user_id
|
||||
|
||||
# userToBeKicked: the _id of the user who was selected to be kicked
|
||||
# kickerUserId: the userId of the user kicking another user
|
||||
# kicker_id: the _id of the user kicking another user
|
||||
userKick: (meetingId, userToBeKicked, kickerUserId, kicker_id) ->
|
||||
kicker = Meteor.Users.findOne({meetingId: meetingId, _id: kicker_id, userId: kickerUserId})
|
||||
toKick = Meteor.Users.findOne({meetingId: meetingId, _id: userToBeKicked})
|
||||
if kicker? and toKick? and kicker.presenter
|
||||
#remove from the collection and dispatch a message to redis
|
||||
removeUserFromMeeting meetingId, toKick.userId, toKick.user_id
|
||||
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Only callable from server
|
||||
# You must need a user's public and private id
|
||||
@removeUserFromMeeting = (meetingId, userId, user_id) ->
|
||||
console.log "#{toKick.userId} is being kicked"
|
||||
console.log "----removed user[" + toKick + "] from " + meetingId
|
||||
u = Meteor.Users.findOne({'userId': userId, _id: user_id})
|
||||
if u?
|
||||
Meteor.Users.remove(user._id) # Should this only happen once we get the server's response?
|
||||
|
||||
console.log "\n\n sending a user_leaving_request for #{meetingId}:#{user._id}"
|
||||
message =
|
||||
"payload":
|
||||
"meeting_id": meetingId
|
||||
"userid": user.userId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "user_leaving_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
if user.userId? and meetingId?
|
||||
publish Meteor.config.redis.channels.toBBBApps.users, message
|
||||
else
|
||||
console.log "did not have enough information to send a user_leaving_request"
|
||||
|
||||
#update a voiceUser - a helper method
|
||||
@updateVoiceUser = (voiceUserObject) ->
|
||||
if voiceUserObject?.user_id?
|
||||
console.log "I am updating the voiceUserObject with the following: " + JSON.stringify voiceUserObject
|
||||
|
||||
u = Meteor.Users.findOne _id: voiceUserObject.user_id
|
||||
if u?
|
||||
if voiceUserObject.talking?
|
||||
Meteor.Users.update({_id:voiceUserObject.user_id}, {$set: {'user.voiceUser.talking':voiceUserObject.talking}}, {multi: false}) # talking
|
||||
if voiceUserObject.joined?
|
||||
Meteor.Users.update({_id:voiceUserObject.user_id}, {$set: {'user.voiceUser.joined':voiceUserObject.joined}}, {multi: false}) # joined
|
||||
if voiceUserObject.locked?
|
||||
Meteor.Users.update({_id:voiceUserObject.user_id}, {$set: {'user.voiceUser.locked':voiceUserObject.locked}}, {multi: false}) # locked
|
||||
if voiceUserObject.muted?
|
||||
Meteor.Users.update({_id:voiceUserObject.user_id}, {$set: {'user.voiceUser.muted':voiceUserObject.muted}}, {multi: false}) # muted
|
||||
if voiceUserObject.listenOnly?
|
||||
Meteor.Users.update({_id:voiceUserObject.user_id}, {$set: {'user.listenOnly':voiceUserObject.listenOnly}}, {multi: false}) # muted
|
||||
else
|
||||
console.log "ERROR! did not find such voiceUser!"
|
||||
|
||||
@addUserToCollection = (meetingId, user) ->
|
||||
userId = user.userid
|
||||
#check if the user is already in the meeting
|
||||
unless Meteor.Users.findOne({userId:userId, meetingId: meetingId})?
|
||||
entry =
|
||||
meetingId: meetingId
|
||||
userId: userId
|
||||
user:
|
||||
userid: user.userid
|
||||
presenter: user.presenter
|
||||
name: user.name
|
||||
phone_user: user.phone_user
|
||||
raise_hand: user.raise_hand
|
||||
has_stream: user.has_stream
|
||||
role: user.role
|
||||
listenOnly: user.listenOnly
|
||||
extern_userid: user.extern_userid
|
||||
permissions: user.permissions
|
||||
locked: user.locked
|
||||
time_of_joining: user.timeOfJoining
|
||||
voiceUser:
|
||||
web_userid: user.voiceUser.web_userid
|
||||
callernum: user.voiceUser.callernum
|
||||
userid: user.voiceUser.userid
|
||||
talking: user.voiceUser.talking
|
||||
joined: user.voiceUser.joined
|
||||
callername: user.voiceUser.callername
|
||||
locked: user.voiceUser.locked
|
||||
muted: user.voiceUser.muted
|
||||
webcam_stream: user.webcam_stream
|
||||
|
||||
id = Meteor.Users.insert(entry)
|
||||
console.log "added user id=[#{id}]:#{user.name}. Users.size is now #{Meteor.Users.find({meetingId: meetingId}).count()}"
|
@ -1,7 +1,7 @@
|
||||
# Publish only the users that are in the particular meetingId
|
||||
# On the client side we pass the meetingId parameter
|
||||
Meteor.publish 'users', (meetingId) ->
|
||||
Meteor.Users.find({meetingId: meetingId})
|
||||
Meteor.Users.find({meetingId: meetingId}, {fields: { 'userId': 0, 'user.userid': 0, 'user.extern_userid': 0, 'user.voiceUser.userid': 0, 'user.voiceUser.web_userid': 0 }})
|
||||
|
||||
Meteor.publish 'chat', (meetingId, me) ->
|
||||
Meteor.Chat.find({$or: [ {'message.chat_type': 'PUBLIC_CHAT', 'meetingId': meetingId},{'message.from_userid': me, 'meetingId': meetingId},{'message.to_userid': me, 'meetingId': meetingId}] })
|
||||
|
@ -1,4 +1,8 @@
|
||||
Meteor.methods
|
||||
#
|
||||
# I dont know if this is okay to be server side. We need to call it from the router, but I don't know if any harm can be caused
|
||||
# by the client calling this
|
||||
#
|
||||
|
||||
# Construct and send a message to bbb-web to validate the user
|
||||
validateAuthToken: (meetingId, userId, authToken) ->
|
||||
@ -15,22 +19,10 @@ Meteor.methods
|
||||
"name": "validate_auth_token"
|
||||
|
||||
if authToken? and userId? and meetingId?
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.meeting, message)
|
||||
publish Meteor.config.redis.channels.toBBBApps.meeting, message
|
||||
else
|
||||
console.log "did not have enough information to send a validate_auth_token message"
|
||||
|
||||
# message should be an object
|
||||
publish: (channel, message) ->
|
||||
console.log "Publishing channel=#{channel}, message=#{JSON.stringify(message)}"
|
||||
if Meteor.redisPubSub?
|
||||
Meteor.redisPubSub.pubClient?.publish(channel, JSON.stringify(message), (err, res) ->
|
||||
if err
|
||||
console.log "err=" + err
|
||||
)
|
||||
else
|
||||
console.log "\n ERROR!! Meteor.redisPubSub was undefined\n"
|
||||
|
||||
|
||||
class Meteor.RedisPubSub
|
||||
constructor: (callback) ->
|
||||
console.log "constructor RedisPubSub"
|
||||
@ -55,7 +47,7 @@ class Meteor.RedisPubSub
|
||||
"header":
|
||||
"name": "get_all_meetings_request"
|
||||
"payload": {} # I need this, otherwise bbb-apps won't recognize the message
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.meeting, message)
|
||||
publish Meteor.config.redis.channels.toBBBApps.meeting, message
|
||||
|
||||
_onMessage: (pattern, channel, jsonMsg) =>
|
||||
# TODO: this has to be in a try/catch block, otherwise the server will
|
||||
@ -72,173 +64,208 @@ class Meteor.RedisPubSub
|
||||
"presentation_cursor_updated_message" # just because it's common. we handle it anyway
|
||||
]
|
||||
|
||||
unless message.header?.name in ignoredEventTypes
|
||||
console.log "eventType=" + message.header?.name #+ "\n"
|
||||
console.log jsonMsg
|
||||
if message?.header? and message?.payload?
|
||||
unless message.header.name in ignoredEventTypes
|
||||
console.log "eventType=" + message.header.name #+ "\n"
|
||||
console.log jsonMsg
|
||||
|
||||
# handle voice events
|
||||
if message.header?.name in ['user_left_voice_message', 'user_joined_voice_message', 'user_voice_talking_message', 'user_voice_muted_message']
|
||||
voiceUser = message.payload?.user?.voiceUser
|
||||
Meteor.call('updateVoiceUser', meetingId, voiceUser)
|
||||
# handle voice events
|
||||
if message.header.name in ['user_left_voice_message', 'user_joined_voice_message', 'user_voice_talking_message', 'user_voice_muted_message']
|
||||
voiceUser = message.payload.user?.voiceUser
|
||||
updateVoiceUser meetingId, voiceUser
|
||||
|
||||
# listen only
|
||||
if message.header?.name is 'user_listening_only'
|
||||
u = Meteor.Users.findOne({userId: message.payload?.userid, meetingId: meetingId})
|
||||
Meteor.Users.update({_id:u._id}, {$set: {'user.listenOnly':message.payload?.listen_only}})
|
||||
# most likely we don't need to ensure that the user's voiceUser's {talking, joined, muted, locked} are false by default #TODO?
|
||||
# listen only
|
||||
if message.header.name is 'user_listening_only'
|
||||
u = Meteor.Users.findOne({userId: message.payload.userid, meetingId: meetingId})
|
||||
updateVoiceUser {'user_id': u._id, 'listenOnly': message.payload.listen_only}
|
||||
# most likely we don't need to ensure that the user's voiceUser's {talking, joined, muted, locked} are false by default #TODO?
|
||||
return
|
||||
|
||||
if message.header?.name is "get_all_meetings_reply"
|
||||
console.log "Let's store some data for the running meetings so that when an HTML5 client joins everything is ready!"
|
||||
listOfMeetings = message.payload?.meetings
|
||||
for meeting in listOfMeetings
|
||||
# we currently do not have voice_conf or duration in this message.
|
||||
Meteor.call("addMeetingToCollection", meeting.meetingID, meeting.meetingName, meeting.recorded, meeting.voiceBridge, meeting.duration)
|
||||
if message.header.name is "get_all_meetings_reply"
|
||||
console.log "Let's store some data for the running meetings so that when an HTML5 client joins everything is ready!"
|
||||
listOfMeetings = message.payload.meetings
|
||||
for meeting in listOfMeetings
|
||||
# we currently do not have voice_conf or duration in this message.
|
||||
addMeetingToCollection meeting.meetingID, meeting.meetingName, meeting.recorded, meeting.voiceBridge, meeting.duration
|
||||
return
|
||||
|
||||
if message.header?.name is "get_users_reply" and message.payload?.requester_id is "nodeJSapp"
|
||||
unless Meteor.Meetings.findOne({MeetingId: message.payload?.meeting_id})?
|
||||
users = message.payload?.users
|
||||
for user in users
|
||||
user.timeOfJoining = message.header?.current_time # TODO this might need to be removed
|
||||
Meteor.call("addUserToCollection", meetingId, user)
|
||||
if message.header.name is "get_users_reply" and message.payload.requester_id is "nodeJSapp"
|
||||
unless Meteor.Meetings.findOne({MeetingId: message.payload.meeting_id})?
|
||||
users = message.payload.users
|
||||
for user in users
|
||||
user.timeOfJoining = message.header.current_time # TODO this might need to be removed
|
||||
addUserToCollection meetingId, user
|
||||
return
|
||||
|
||||
if message.header?.name is "user_joined_message"
|
||||
user = message.payload.user
|
||||
user.timeOfJoining = message.header?.current_time
|
||||
Meteor.call("addUserToCollection", meetingId, user)
|
||||
if message.header.name is "user_joined_message"
|
||||
user = message.payload.user
|
||||
user.timeOfJoining = message.header.current_time
|
||||
addUserToCollection meetingId, user
|
||||
return
|
||||
|
||||
if message.header?.name is "user_left_message"
|
||||
userId = message.payload?.user?.userid
|
||||
if userId? and meetingId?
|
||||
Meteor.call("removeUserFromCollection", meetingId, userId)
|
||||
if message.header.name is "user_left_message"
|
||||
userId = message.payload.user?.userid
|
||||
if userId? and meetingId?
|
||||
removeUserFromMeeting meetingId, userId
|
||||
return
|
||||
|
||||
if message.header?.name is "get_chat_history_reply" and message.payload?.requester_id is "nodeJSapp"
|
||||
unless Meteor.Meetings.findOne({MeetingId: message.payload?.meeting_id})?
|
||||
for chatMessage in message.payload?.chat_history
|
||||
Meteor.call("addChatToCollection", meetingId, chatMessage)
|
||||
if message.header.name is "get_chat_history_reply" and message.payload.requester_id is "nodeJSapp"
|
||||
unless Meteor.Meetings.findOne({MeetingId: message.payload.meeting_id})?
|
||||
for chatMessage in message.payload.chat_history
|
||||
addChatToCollection meetingId, chatMessage
|
||||
return
|
||||
|
||||
if message.header?.name is "send_public_chat_message" or message.header?.name is "send_private_chat_message"
|
||||
messageObject = message.payload?.message
|
||||
if message.header.name is "send_public_chat_message" or message.header.name is "send_private_chat_message"
|
||||
messageObject = message.payload.message
|
||||
# use current_time instead of message.from_time so that the chats from Flash and HTML5 have uniform times
|
||||
messageObject.from_time = message.header.current_time
|
||||
addChatToCollection meetingId, messageObject
|
||||
return
|
||||
|
||||
# use current_time instead of message.from_time so that the chats from Flash and HTML5 have uniform times
|
||||
messageObject.from_time = message.header?.current_time
|
||||
if message.header.name is "meeting_created_message"
|
||||
meetingName = message.payload.name
|
||||
intendedForRecording = message.payload.recorded
|
||||
voiceConf = message.payload.voice_conf
|
||||
duration = message.payload.duration
|
||||
addMeetingToCollection meetingId, meetingName, intendedForRecording, voiceConf, duration
|
||||
return
|
||||
|
||||
Meteor.call("addChatToCollection", meetingId, messageObject)
|
||||
if message.header.name is "presentation_shared_message"
|
||||
presentationId = message.payload.presentation?.id
|
||||
# change the currently displayed presentation to presentation.current = false
|
||||
Meteor.Presentations.update({"presentation.current": true, meetingId: meetingId},{$set: {"presentation.current": false}})
|
||||
|
||||
if message.header?.name is "meeting_created_message"
|
||||
meetingName = message.payload?.name
|
||||
intendedForRecording = message.payload?.recorded
|
||||
voiceConf = message.payload?.voice_conf
|
||||
duration = message.payload?.duration
|
||||
Meteor.call("addMeetingToCollection", meetingId, meetingName, intendedForRecording, voiceConf, duration)
|
||||
#update(if already present) entirely the presentation with the fresh data
|
||||
removePresentationFromCollection meetingId, presentationId
|
||||
addPresentationToCollection meetingId, message.payload.presentation
|
||||
|
||||
if message.header?.name is "presentation_shared_message"
|
||||
presentationId = message.payload?.presentation?.id
|
||||
# change the currently displayed presentation to presentation.current = false
|
||||
Meteor.Presentations.update({"presentation.current": true, meetingId: meetingId},{$set: {"presentation.current": false}})
|
||||
for slide in message.payload.presentation?.pages
|
||||
addSlideToCollection meetingId, message.payload.presentation?.id, slide
|
||||
if slide.current
|
||||
displayThisSlide meetingId, slide.id, slide
|
||||
return
|
||||
|
||||
#update(if already present) entirely the presentation with the fresh data
|
||||
Meteor.call("removePresentationFromCollection", meetingId, presentationId)
|
||||
Meteor.call("addPresentationToCollection", meetingId, message.payload?.presentation)
|
||||
if message.header.name is "get_presentation_info_reply" and message.payload.requester_id is "nodeJSapp"
|
||||
for presentation in message.payload.presentations
|
||||
addPresentationToCollection meetingId, presentation
|
||||
|
||||
for slide in message.payload?.presentation?.pages
|
||||
Meteor.call("addSlideToCollection", meetingId, message.payload?.presentation?.id, slide)
|
||||
if slide.current
|
||||
Meteor.call("displayThisSlide", meetingId, slide.id, slide)
|
||||
for page in presentation.pages
|
||||
#add the slide to the collection
|
||||
addSlideToCollection meetingId, presentation.id, page
|
||||
|
||||
if message.header?.name is "get_presentation_info_reply" and message.payload?.requester_id is "nodeJSapp"
|
||||
for presentation in message.payload?.presentations
|
||||
Meteor.call("addPresentationToCollection", meetingId, presentation)
|
||||
#request for shapes
|
||||
whiteboardId = "#{presentation.id}/#{page.num}" # d2d9a672040fbde2a47a10bf6c37b6a4b5ae187f-1404411622872/1
|
||||
console.log "the whiteboard_id here is:" + whiteboardId
|
||||
|
||||
for page in presentation.pages
|
||||
#add the slide to the collection
|
||||
Meteor.call("addSlideToCollection", meetingId, presentation.id, page)
|
||||
message =
|
||||
"payload":
|
||||
"meeting_id": meetingId
|
||||
"requester_id": "nodeJSapp"
|
||||
"whiteboard_id": whiteboardId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "get_whiteboard_shapes_request"
|
||||
"version": "0.0.1"
|
||||
|
||||
#request for shapes
|
||||
whiteboardId = "#{presentation.id}/#{page.num}" # d2d9a672040fbde2a47a10bf6c37b6a4b5ae187f-1404411622872/1
|
||||
console.log "the whiteboard_id here is:" + whiteboardId
|
||||
if whiteboardId? and meetingId?
|
||||
publish Meteor.config.redis.channels.toBBBApps.whiteboard, message
|
||||
else
|
||||
console.log "did not have enough information to send a user_leaving_request"
|
||||
return
|
||||
|
||||
message =
|
||||
"payload":
|
||||
"meeting_id": meetingId
|
||||
"requester_id": "nodeJSapp"
|
||||
"whiteboard_id": whiteboardId
|
||||
"header":
|
||||
"timestamp": new Date().getTime()
|
||||
"name": "get_whiteboard_shapes_request"
|
||||
"version": "0.0.1"
|
||||
if message.header.name is "presentation_page_changed_message"
|
||||
newSlide = message.payload.page
|
||||
displayThisSlide meetingId, newSlide?.id, newSlide
|
||||
return
|
||||
|
||||
if whiteboardId? and meetingId?
|
||||
Meteor.call('publish', Meteor.config.redis.channels.toBBBApps.whiteboard, message)
|
||||
else
|
||||
console.log "did not have enough information to send a user_leaving_request"
|
||||
if message.header.name is "get_whiteboard_shapes_reply" and message.payload.requester_id is "nodeJSapp"
|
||||
for shape in message.payload.shapes
|
||||
whiteboardId = shape.wb_id
|
||||
addShapeToCollection meetingId, whiteboardId, shape
|
||||
return
|
||||
|
||||
if message.header?.name is "presentation_page_changed_message"
|
||||
newSlide = message.payload?.page
|
||||
Meteor.call("displayThisSlide", meetingId, newSlide?.id, newSlide)
|
||||
if message.header.name is "send_whiteboard_shape_message"
|
||||
shape = message.payload.shape
|
||||
whiteboardId = shape?.wb_id
|
||||
addShapeToCollection meetingId, whiteboardId, shape
|
||||
return
|
||||
|
||||
if message.header?.name is "get_whiteboard_shapes_reply" and message.payload?.requester_id is "nodeJSapp"
|
||||
for shape in message.payload.shapes
|
||||
whiteboardId = shape.wb_id
|
||||
Meteor.call("addShapeToCollection", meetingId, whiteboardId, shape)
|
||||
if message.header.name is "presentation_cursor_updated_message"
|
||||
x = message.payload.x_percent
|
||||
y = message.payload.y_percent
|
||||
Meteor.Presentations.update({"presentation.current": true, meetingId: meetingId},{$set: {"pointer.x": x, "pointer.y": y}})
|
||||
return
|
||||
|
||||
if message.header?.name is "send_whiteboard_shape_message"
|
||||
shape = message.payload?.shape
|
||||
whiteboardId = shape?.wb_id
|
||||
Meteor.call("addShapeToCollection", meetingId, whiteboardId, shape)
|
||||
if message.header.name is "whiteboard_cleared_message"
|
||||
whiteboardId = message.payload.whiteboard_id
|
||||
removeAllShapesFromSlide meetingId, whiteboardId
|
||||
return
|
||||
|
||||
if message.header?.name is "presentation_cursor_updated_message"
|
||||
x = message.payload?.x_percent
|
||||
y = message.payload?.y_percent
|
||||
Meteor.Presentations.update({"presentation.current": true, meetingId: meetingId},{$set: {"pointer.x": x, "pointer.y": y}})
|
||||
if message.header.name is "undo_whiteboard_request"
|
||||
whiteboardId = message.payload.whiteboard_id
|
||||
shapeId = message.payload.shape_id
|
||||
removeShapeFromSlide meetingId, whiteboardId, shapeId
|
||||
return
|
||||
|
||||
if message.header?.name is "whiteboard_cleared_message"
|
||||
whiteboardId = message.payload?.whiteboard_id
|
||||
Meteor.call("removeAllShapesFromSlide", meetingId, whiteboardId)
|
||||
if message.header.name is "presenter_assigned_message"
|
||||
newPresenterId = message.payload.new_presenter_id
|
||||
if newPresenterId?
|
||||
# reset the previous presenter
|
||||
Meteor.Users.update({"user.presenter": true, meetingId: meetingId},{$set: {"user.presenter": false}})
|
||||
# set the new presenter
|
||||
Meteor.Users.update({"user.userid": newPresenterId, meetingId: meetingId},{$set: {"user.presenter": true}})
|
||||
return
|
||||
|
||||
if message.header?.name is "undo_whiteboard_request"
|
||||
whiteboardId = message.payload?.whiteboard_id
|
||||
shapeId = message.payload?.shape_id
|
||||
Meteor.call("removeShapeFromSlide", meetingId, whiteboardId, shapeId)
|
||||
if message.header.name is "presentation_page_resized_message"
|
||||
slideId = message.payload.page?.id
|
||||
heightRatio = message.payload.page?.height_ratio
|
||||
widthRatio = message.payload.page?.width_ratio
|
||||
xOffset = message.payload.page?.x_offset
|
||||
yOffset = message.payload.page?.y_offset
|
||||
presentationId = slideId.split("/")[0]
|
||||
Meteor.Slides.update({presentationId: presentationId, "slide.current": true}, {$set: {"slide.height_ratio": heightRatio, "slide.width_ratio": widthRatio, "slide.x_offset": xOffset, "slide.y_offset": yOffset}})
|
||||
return
|
||||
|
||||
if message.header?.name is "presenter_assigned_message"
|
||||
newPresenterId = message.payload?.new_presenter_id
|
||||
if newPresenterId?
|
||||
# reset the previous presenter
|
||||
Meteor.Users.update({"user.presenter": true, meetingId: meetingId},{$set: {"user.presenter": false}})
|
||||
# set the new presenter
|
||||
Meteor.Users.update({"user.userid": newPresenterId, meetingId: meetingId},{$set: {"user.presenter": true}})
|
||||
if message.header.name is "user_raised_hand_message"
|
||||
userId = message.payload.userid
|
||||
# update the user
|
||||
Meteor.Users.update({"user.userid": userId, meetingId: meetingId},{$set: {"user.raise_hand": true}}) #not sure why but message.payload.raise_hand is awlays false
|
||||
return
|
||||
|
||||
if message.header?.name is "presentation_page_resized_message"
|
||||
slideId = message.payload?.page?.id
|
||||
heightRatio = message.payload?.page?.height_ratio
|
||||
widthRatio = message.payload?.page?.width_ratio
|
||||
xOffset = message.payload?.page?.x_offset
|
||||
yOffset = message.payload?.page?.y_offset
|
||||
presentationId = slideId.split("/")[0]
|
||||
Meteor.Slides.update({presentationId: presentationId, "slide.current": true},
|
||||
{$set: {"slide.height_ratio": heightRatio, "slide.width_ratio": widthRatio, "slide.x_offset": xOffset, "slide.y_offset": yOffset}})
|
||||
if message.header.name is "user_lowered_hand_message"
|
||||
userId = message.payload.userid
|
||||
# update the user
|
||||
Meteor.Users.update({"user.userid": userId, meetingId: meetingId},{$set: {"user.raise_hand": false}}) #not sure why but message.payload.raise_hand is awlays false
|
||||
return
|
||||
|
||||
if message.header?.name is "user_raised_hand_message"
|
||||
userId = message.payload?.userid
|
||||
# update the user
|
||||
Meteor.Users.update({"user.userid": userId, meetingId: meetingId},{$set: {"user.raise_hand": true}}) #not sure why but message.payload?.raise_hand is awlays false
|
||||
if message.header.name is "recording_status_changed_message"
|
||||
intendedForRecording = message.payload.recorded
|
||||
currentlyBeingRecorded = message.payload.recording
|
||||
Meteor.Meetings.update({meetingId: meetingId, intendedForRecording: intendedForRecording}, {$set: {currentlyBeingRecorded: currentlyBeingRecorded}})
|
||||
return
|
||||
|
||||
if message.header?.name is "user_lowered_hand_message"
|
||||
userId = message.payload?.userid
|
||||
# update the user
|
||||
Meteor.Users.update({"user.userid": userId, meetingId: meetingId},{$set: {"user.raise_hand": false}}) #not sure why but message.payload?.raise_hand is awlays false
|
||||
if message.header.name in ["meeting_ended_message", "meeting_destroyed_event",
|
||||
"end_and_kick_all_message", "disconnect_all_users_message"]
|
||||
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||
console.log "there are #{Meteor.Users.find({meetingId: meetingId}).count()} users in the meeting"
|
||||
for user in Meteor.Users.find({meetingId: meetingId}).fetch()
|
||||
removeUserFromMeeting meetingId, user.userId
|
||||
#TODO should we clear the chat messages for that meeting?!
|
||||
unless message.header.name is "disconnect_all_users_message"
|
||||
removeMeetingFromCollection meetingId
|
||||
return
|
||||
|
||||
if message.header?.name is "recording_status_changed_message"
|
||||
intendedForRecording = message.payload?.recorded
|
||||
currentlyBeingRecorded = message.payload?.recording
|
||||
Meteor.Meetings.update({meetingId: meetingId, intendedForRecording: intendedForRecording}, {$set: {currentlyBeingRecorded: currentlyBeingRecorded}})
|
||||
# --------------------------------------------------------------------------------------------
|
||||
# Private methods on server
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
if message.header?.name in ["meeting_ended_message", "meeting_destroyed_event",
|
||||
"end_and_kick_all_message", "disconnect_all_users_message"]
|
||||
if Meteor.Meetings.findOne({meetingId: meetingId})?
|
||||
console.log "there are #{Meteor.Users.find({meetingId: meetingId}).count()} users in the meeting"
|
||||
for user in Meteor.Users.find({meetingId: meetingId}).fetch()
|
||||
Meteor.call("removeUserFromCollection", meetingId, user.userId)
|
||||
#TODO should we clear the chat messages for that meeting?!
|
||||
unless message.header?.name is "disconnect_all_users_message"
|
||||
Meteor.call("removeMeetingFromCollection", meetingId)
|
||||
# message should be an object
|
||||
@publish = (channel, message) ->
|
||||
console.log "Publishing channel=#{channel}, message=#{JSON.stringify(message)}"
|
||||
if Meteor.redisPubSub?
|
||||
Meteor.redisPubSub.pubClient.publish(channel, JSON.stringify(message), (err, res) ->
|
||||
if err
|
||||
console.log "err=" + err
|
||||
)
|
||||
else
|
||||
console.log "\n ERROR!! Meteor.redisPubSub was undefined\n"
|
||||
|
@ -11,6 +11,15 @@ Meteor.startup(function () {
|
||||
|
||||
});
|
||||
###
|
||||
Meteor.methods
|
||||
getMyInfo: (uId) ->
|
||||
u = Meteor.Users.findOne("userId": uId)
|
||||
if u?
|
||||
{
|
||||
userId: u.userId
|
||||
DBID: u._id
|
||||
name: u.user.name
|
||||
}
|
||||
|
||||
Meteor.startup ->
|
||||
console.log "server start"
|
||||
|
Loading…
Reference in New Issue
Block a user