def post(self): actor = self.get_current_actor() if(isinstance(actor, model.User)): locationUUID = self.get_argument("locationUUID") location = state.get_obj(locationUUID, Location) if(location==None): raise HTTPError(400, "Specified location UUID %s\ didn't exist or wasn't a valid location."%locationUUID) return None # Trigger the actual event. leaveLocationEvent = Event("USER_LEFT_LOCATION", actor.uuid, params={"location":location.uuid}) leaveLocationEvent.dispatch() else: locationUUID = self.get_argument("locationUUID") location = state.get_obj(locationUUID, Location) if(location==None): raise HTTPError(400, "Specified location UUID %s\ didn't exist or wasn't a valid location."%locationUUID) return None userUUID = self.get_argument("userUUID") leaveLocationEvent = Event("USER_LEFT_LOCATION", userUUID, params={"location":location.uuid}) leaveLocationEvent.dispatch()
def __init__(self, meetingUUID, creatorUUID, text, assignedByUUID=None, assignedToUUID=None,taskUUID=None, createdAt=None, assignedAt=None, color=None): MeetingObject.__init__(self, creatorUUID, meetingUUID, createdAt, taskUUID) self.text = text self.assignedAt=assignedAt if(assignedByUUID!=None): self.assignedBy = state.get_obj(assignedByUUID, Actor) else: self.assignedBy = None if(assignedToUUID!=None): self.assignedTo = state.get_obj(assignedToUUID, User) assignedTo.assignTask(self) else: self.assignedTo = None if(color==None): self.color = "888888" else: self.color = color # this field tracks whether or not this idea(task) was shared. # when a task is created, the system will check to see if it's # a double. if it is, the non-public version of the task # will get this flag set. self.shared = False self.likers = set()
def __init__(self, meetingUUID, creatorUUID, text, startTime=None, stopTime=None, status=None, startActorUUID=None, stopActorUUID=None, color=None, topicUUID=None, createdAt=None): MeetingObject.__init__(self, creatorUUID, meetingUUID, createdAt, topicUUID) self.text = text self.startTime = startTime if(status==None): self.status = Topic.FUTURE else: self.status = status if(startActorUUID!=None): self.startActor = state.get_obj(startActorUUID, Actor) else: self.startActor = None self.stopTime = stopTime if(stopActorUUID != None): self.stopActor = state.get_obj(stopActorUUID, Actor) else: self.stopActor = None # Need to decide later how to represent color. Almost certainly # going to just use HTML hex colors for ease, although I need to # check and see if there's an easy way to convert those to something # that objC can use. self.color = color
def post(self): actor = self.get_current_actor() newTaskEvent = Event("NEW_TASK", actor.uuid , actor.getMeeting().uuid, params={"text": self.get_argument("text"), "createInPool": self.get_argument("createInPool")=="1", "createdBy": state.get_obj(self.get_argument("createdBy", None), Actor), "assignedBy": state.get_obj(self.get_argument("assignedBy", None), Actor), "color": self.get_argument("color", None)}) newTaskEvent.dispatch() return
def _handleAddActorDevice(event): # connects devices with their actors. actor = state.get_obj(event.params["actor"], model.Actor) device = state.get_obj(event.params["device"], model.Device) # need to remove device from previous actor. if device.actor!=None: device.actor.removeDevice(device) actor.addDevice(device) return event
def _handleLikeTask(event): task = state.get_obj(event.params["taskUUID"], model.Task) liker = state.get_obj(event.actor.uuid, model.Actor) # edit the task itself to have another like (or not - we don't allow # multiple likes from the same person on a task). task.addLike(liker) # TODO need to make this time get saved properly, otherwise I worry that # replaying will break on these kinds of events. event.queue(e.Event("UPDATE_STATUS", liker.uuid, None, {"status": "liked task", "time": time.time()})) event.meeting.eventHistoryReadable.append(liker.name + " liked task \""+task.text+"\"") return event
def _handleNewMeeting(event): if len(event.results)!=0: d = event.results["meeting"] logging.debug(d) newMeeting = model.Meeting(event.params["room"], d["title"], d["uuid"], d["startedAt"], d["isNamed"]) else: newMeeting = model.Meeting(event.params["room"]) # once we have the meeting, push it back into the event object. # pushing it into params because the outer meeting value is # just for specifying which meeting an event is taking place in, # and this event type happens outside of a meeting context. event.addResult("meeting", newMeeting) # now register that meeting with the room. room = state.get_obj(event.params["room"], model.Room) room.set_meeting(newMeeting) # add this event to the meeting, so it's included at the beginning of # every meeting history. newMeeting.eventHistory.append(event) newMeeting.eventHistoryReadable.append("Meeting was created") return event
def _handleLeftLocation(event): location = state.get_obj(event.params["location"], model.Location) location.userLeft(event.actor) # loop through the remaining users and see if any of them have # registered devices / if the location has a registered device. # There are some weird conflicts at the moment where when an ipad is # logged into the system as a user, not as a location. So basically # it's not enough to see that the location has no logged in users and # then shutting it down. if ((len(location.getUsers())==0 and location.isInMeeting()) or len(location.getDevices())==0): locationLeftMeetingEvent = e.Event("LOCATION_LEFT_MEETING", location.uuid, None, {"meeting":location.meeting.uuid}) event.queue(locationLeftMeetingEvent) # Turning this off for now - I think we can live without it. # The USER_JOINED_LOCATION event will fire, and clients should be able # to imply the rest. # if location.isInMeeting(): # userLeftEvent = Event("LEFT_ROOM", event.user.uuid, # location.meeting.uuid) # # # TODO Need to do something about dispatch order here. This joined # # event is going to finish dispatching before the joined_location # # event does, which might cause some trouble. Need a way for events # # to dispatch in the order they're created, not the order they're # # executed. # userLeftEvent.dispatch() return event
def __init__(self, roomUUID, title=None, meetingUUID=None, startedAt=None, isNamed=False): self.uuid = meetingUUID YarnBaseType.__init__(self) self.room = state.get_obj(roomUUID, Room) self.title = title if isNamed==False: self.isNamed = False else: self.isNamed = True if startedAt==None: self.startedAt = time.time() else: self.startedAt = startedAt self.endedAt = None self.isLive = False self.allParticipants = set() self.locations = set() self.eventHistory = [] self.eventHistoryReadable = [] self.topics = [] self.tasks = []
def post(self): # have to do a bit of a dance to figure out who this is. actor = self.get_current_actor() userUUID = None # only users can thumbs up. ignore requests from locations if isinstance(actor, model.User): userUUID = actor.uuid if isinstance(actor, model.Location): logging.debug("Got a thumbs up request from a Location") # if it's a location, look at the userUUID field. user = state.get_obj(self.get_argument("userUUID"), model.User) # now double check that that user is in the location if(user!=None and user in actor.users): userUUID = user.uuid if(userUUID != None): logging.debug("handling thumbs up for userUUID: %s", str(userUUID)) thumbsUpEvent = Event("THUMBS_UP", userUUID, actor.getMeeting().uuid, params = {}) thumbsUpEvent.dispatch() else: logging.debug("Received a thumbs up call that went wrong.")
def post(self): actor = self.get_current_actor() meeting = state.get_obj(self.get_argument("meetingUUID"), Meeting) editMeetingEvent = Event("EDIT_MEETING", actor.uuid, params={"meeting":meeting.uuid, "title": self.get_argument("title")}) editMeetingEvent.dispatch() return
def _handleEditMeeting(event): meeting = state.get_obj(event.params["meeting"], model.Meeting) title = event.params["title"] meeting.setTitle(title) meeting.eventHistoryReadable.append("Meeting name changed to "+title) return event
def post(self): actor = self.get_current_actor() if isinstance(actor, model.User): locationUUID = self.get_argument("locationUUID") location = state.get_obj(locationUUID, Location) if(location==None): raise HTTPError(400, "Specified location UUID %s\ didn't exist or wasn't a valid location."%locationUUID) return None userUUID = self.get_argument("userUUID") # Trigger the actual event. if userUUID=="null": joinLocationEvent = Event("USER_JOINED_LOCATION", actor.uuid, params={"location":location.uuid}) joinLocationEvent.dispatch() else: joinLocationEvent = Event("USER_JOINED_LOCATION", userUUID, params={"location":location.uuid}) joinLocationEvent.dispatch() elif isinstance(actor, model.Location): # if the actor is a location (eg the join is coming from an ipad) # then we're going to add the specified user to to the specified # location. # This is basically for adding people "in spirit" who are not # logged in on specific devices. These users will be inMeeting, # but not loggedIn. # [this logic is nearly the same as above and could be collapsed, # but I'm going to keep them separate for conceptual reasons.] locationUUID = self.get_argument("locationUUID") location = state.get_obj(locationUUID, Location) if(location==None): raise HTTPError(400, "Specified location UUID %s\ didn't exist or wasn't a valid location."%locationUUID) return None userUUID = self.get_argument("userUUID") joinLocationEvent = Event("USER_JOINED_LOCATION", userUUID, params={"location":location.uuid}) joinLocationEvent.dispatch()
def __init__(self, creatorUUID, meetingUUID, createdAt=None, meetingObjUUID=None): self.uuid = meetingObjUUID YarnBaseType.__init__(self) # TODO we almost certainly want to unswizzle these UUIDS # to their actual objects. When we do that, we'll need to # switch all the getDict methods to getting the UUID instead # of just taking the whole object like it does now. self.createdBy = state.get_obj(creatorUUID, Actor) if createdAt==None: self.createdAt = time.time() else: self.createdAt = createdAt self.meeting = state.get_obj(meetingUUID, Meeting)
def get_current_device(self): # All logged-in users should have a deviceUUID. deviceUUID = self.get_cookie("deviceUUID") device = state.get_obj(deviceUUID, Device) if(device==None): raise HTTPError(400, "Specified device UUID %s\ didn't exist or wasn't a valid device."%deviceUUID) return None return device
def _handleDeleteTopic(event): topic = state.get_obj(event.params["topicUUID"], model.Topic) deletedAt = time.time() event.meeting.removeTopic(topic) event.queue(e.Event("UPDATE_STATUS", event.actor.uuid, None, {"status": "deleted topic", "time": deletedAt})) #needed to keep track of statuses on client-side event.params["deletedAt"] = deletedAt event.meeting.eventHistoryReadable.append(event.actor.name+" deleted topic ("+topic.text+")") return event
def post(self): actor = self.get_current_actor() task = state.get_obj(self.get_argument("taskUUID"), Task) if(actor not in task.likers): likeTaskEvent = Event("LIKE_TASK", actor.uuid, actor.getMeeting().uuid, params = {"taskUUID":self.get_argument("taskUUID")}) likeTaskEvent.dispatch() else: raise HTTPError(403, "You cannot like an idea more\ than once.")
def __str__(self): out = "" if self.eventType == EventType.types["NEW_MEETING"]: out = "Class started." elif self.eventType == EventType.types["USER_JOINED_LOCATION"]: location = state.get_obj(self.params["location"], model.Location) out = self.actor.name + " joined " + location.name elif self.eventType == EventType.types["USER_LEFT_LOCATION"]: location = state.get_obj(self.params["location"], model.Location) out = self.actor.name + " left " + location.name elif self.eventType == EventType.types["LOCATION_JOINED_MEETING"]: meeting = state.get_obj(self.params["meeting"], model.Meeting) out = self.actor.name + " has conneted to meeting in room " + \ meeting.room.name elif self.eventType == EventType.types["LOCATION_LEFT_MEETING"]: meeting = state.get_obj(self.params["meeting"], model.Meeting) out = self.actor.name + " has left meeting in room " + \ meeting.room.name elif self.eventType == EventType.types["END_MEETING"]: out = "Class ended." elif self.eventType == EventType.types["NEW_TOPIC"]: out = self.actor.name + " added topic \"" + self.params["text"] +\ "\"." elif self.eventType == EventType.types["UPDATE_TOPIC"]: verb = {"CURRENT":"started", "PAST":"stopped"} topic = state.get_obj(self.params["topicUUID"], model.Topic) out = self.actor.name + " " + verb[self.params["status"]] +\ " topic \"" + topic.text + "\"." elif self.eventType == EventType.types["NEW_TASK"]: # going to want to refactor this out on master if self.params["createInPool"]: # this might be subtly wrong - I think the actor is right # here, but we might want to plug into assignedBy/createdBy out = self.actor.name + " suggested idea \"" +\ self.params["text"] + "\" to the group." else: out = self.actor.name + " created idea \"" +\ self.params["text"] + "\"." elif self.eventType == EventType.types["DELETE_TASK"]: out = self.actor.name + " deleted an idea." elif self.eventType == EventType.types["ASSIGN_TASK"]: task = state.get_obj(self.params["taskUUID"], model.Task) if(self.params["deassign"]): out = self.actor.name + " deassigned idea \"" + task.text else: assignedTo = state.get_obj(self.params["assignedTo"], model.User) out = self.actor.name + " assigned idea \"" + task.text +"\" to "\ + assignedTo.name + "." else: out = "This event has no string representation." return out
def _handleAssignTask(event): task = state.get_obj(event.params["taskUUID"], model.Task) task.assignedAt = time.time() assignedBy = state.get_obj(event.actor.uuid, model.Actor) deassign = event.params["deassign"] if(not deassign): assignedTo = state.get_obj(event.params["assignedTo"], model.User) task.assign(assignedBy,assignedTo, None) event.queue(e.Event("UPDATE_STATUS", assignedBy.uuid, None, {"status": "moved task", "time": task.assignedAt})) event.queue(e.Event("UPDATE_STATUS", assignedTo.uuid, None, {"status": "claimed task", "time": task.assignedAt})) event.meeting.eventHistoryReadable.append(assignedBy.name + " moved task ("+task.text+") to "+assignedTo.name) else: task.deassign(assignedBy) event.queue(e.Event("UPDATE_STATUS", assignedBy.uuid, None, {"status": "deassigned task", "time": task.assignedAt})) event.meeting.eventHistoryReadable.append(assignedBy.name + " deassigned task ("+task.text+")") event.params["assignedAt"]=task.assignedAt return event
def _handleDeleteTask(event): logging.debug(event.params["taskUUID"]) task = state.get_obj(event.params["taskUUID"], model.Task) logging.debug(task) deletedAt = time.time() event.meeting.removeTask(task) event.queue(e.Event("UPDATE_STATUS", event.actor.uuid, None, {"status": "deleted task", "time": deletedAt})) #needed to keep track of statuses on client-side event.params["deletedAt"] = deletedAt event.meeting.eventHistoryReadable.append(event.actor.name+" deleted task ("+task.text+")") return event
def post(self): # first, check and see if the connection included a device cookie # to identify itself. This is very similar to get_current_actor in # BaseHandler, but slightly different because if they don't have one, # we bounce them to the resource where they can get on. deviceUUID = self.get_cookie("deviceUUID") if(deviceUUID==None): device = None else: device = state.get_obj(deviceUUID, Device) if(device==None): logging.debug("Received a connection that didn't have a device\ cookie yet.") addDeviceEvent = Event("NEW_DEVICE") addDeviceEvent = addDeviceEvent.dispatch() device = addDeviceEvent.results["device"] logging.info("Set up new device with UUID %s"%device.uuid) self.set_cookie("deviceUUID", device.uuid) # take the actorUUID and associate the specified device with it. actorUUID = self.get_argument("actorUUID") actor = state.get_obj(actorUUID, Actor) if(actor==None): raise HTTPError(400, "Specified actor UUID %s\ didn't exist or wasn't a valid actor."%actorUUID) return None addActorDeviceEvent = Event("ADD_ACTOR_DEVICE", actor.uuid, params={"actor":actor.uuid, "device":device.uuid}) addActorDeviceEvent.dispatch() # otherwise, set the secure cookie for the user ID. logging.info("Associated device (%s) with actor '%s'."%(device.uuid, actor.name))
def _handleEditTask(event): text = event.params["text"] task = state.get_obj(event.params["taskUUID"], model.Task) editedAt = time.time() event.meeting.eventHistoryReadable.append(event.actor.name+" changed task ("+task.text+") to task ("+text+")") task.setText(text) event.queue(e.Event("UPDATE_STATUS", event.actor.uuid, None, {"status": "edited task", "time": editedAt})) #needed to keep track of statuses on client-side event.params["editedAt"] = editedAt return event
def post(self): actor = self.get_current_actor() # do some quick validation - we should only a restart operation if # it's a past topic. ignore the for current and future items. topic = state.get_obj(self.get_argument("topicUUID"), Topic) if(topic.status==Topic.PAST): newTopicEvent = Event("RESTART_TOPIC", actor.uuid , actor.getMeeting().uuid, params={"topicUUID": self.get_argument("topicUUID")}) newTopicEvent.dispatch() else: logging.warning("Received request to restart a non-PAST topic. \ Ignoring it.") return
def _handleUpdateTopic(event): # in this handler, we need to manage some higher level logic. # We need to make sure that we keep the overall state proper. # IF there's a current topic open, AND the request is to # start a new topic, we want to close out the old topic # before starting the new one. topic = state.get_obj(event.params["topicUUID"], model.Topic) logging.info("Updating topic %s to have status %s", topic, event.params["status"]) status = event.params["status"] editedAt = time.time() actor = event.actor # check and see if we're trying to start a topic. if(status=="CURRENT"): # now go looking for the current item currentTopic = [t for t in actor.getMeeting().topics if t.status=="CURRENT"] if len(currentTopic) > 1: logging.warning("Found multiple current topics. Badness.") elif len(currentTopic) == 1: currentTopic = currentTopic[0] logging.debug("Found current topic, setting its status to" +" PAST") updateCurrentTopicEvent = e.Event("UPDATE_TOPIC", actor.uuid, actor.getMeeting().uuid, params={"topicUUID":currentTopic.uuid, "status":"PAST"}) updateCurrentTopicEvent.dispatch() else: logging.debug("No current topic found, continuing.") # now we can set the target topic to its target status.) topic.setStatus(status, event.actor, None) event.queue(e.Event("UPDATE_STATUS", event.actor.uuid, None, {"status": "updated topic", "time": editedAt})) #needed to keep track of statuses on client-side event.params["editedAt"] = editedAt event.meeting.eventHistoryReadable.append(event.actor.name+ " changed the status of topic ("+ topic.text+") to "+status) return event
def _handleJoinedLocation(event): location = state.get_obj(event.params["location"], model.Location) location.userJoined(event.actor) joinedAt = time.time() updateStatusEvent = e.Event("UPDATE_STATUS", event.actor.uuid, None, {"status": "joined location", "time": joinedAt}) event.queue(updateStatusEvent) event.params["joinedAt"] = joinedAt if location.isInMeeting(): event.meeting = location.meeting if event.meeting != None: event.meeting.eventHistoryReadable.append(event.actor.name+ " joined the meeting in location "+location.name) return event
def _handleRestartTopic(event): topic = state.get_obj(event.params["topicUUID"], model.Topic) logging.debug("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") # if it's a past topic, create a new one and make it current. # if it's a future topic, just make it current # if it's a current topic, do nothing if topic.status == model.Topic.PAST: newTopicEvent = e.Event("NEW_TOPIC", event.actor.uuid, event.meeting.uuid, {"text": topic.text}) newTopicEvent = newTopicEvent.dispatch() topic = newTopicEvent.results["topic"] event.queue(e.Event("UPDATE_TOPIC", event.actor.uuid, event.meeting.uuid, {"topicUUID": topic.uuid, "status": model.Topic.CURRENT})) elif topic.status == model.Topic.FUTURE: # if it's a future topic, we shouldn't be getting a restart request at # all. filter these out before they get this far. pass return event
def _handleLocationJoinedMeeting(event): # For all the users in this location, fire joined messages location = event.actor meeting = state.get_obj(event.params["meeting"], model.Meeting) location.joinedMeeting(meeting) if not meeting.isNamed: title = "Meeting with " for location in meeting.locations: if location.isLoggedIn: title = title +location.name+", " title = title[0:-2] editMeetingEvent = e.Event("EDIT_MEETING", None, None, {"meeting":meeting.uuid, "title": title}) event.queue(editMeetingEvent) meeting.eventHistoryReadable.append(location.name + " joined the meeting") return event
def post(self): # TODO Check if the current actor has a location set yet. If not, # do we want to reject the query? I think so... actor = self.get_current_actor() location = None if isinstance(actor, model.User): # If we've got a user, make sure they have a location set alrady. # If they don't, reject the request outright. user = actor if user.location == None: raise HTTPError(400, "Specified user " + user.name + " isn't yet in a location, so can not leave meeting.") return location = user.location logging.debug("User %s is trying to leave a meeting on their behalf\ of their location %s"%(user.name, location.name)) else: location = actor logging.debug("Actor is a location: " + location.name) # from this point forward, we're telling the location what to join, # not the user. the location is the user's location if(not location.isInMeeting()): logging.warning("Location has no meeting: %s. Join a meeting first.", location) meetingUUID = self.get_argument("meetingUUID") meeting = state.get_obj(meetingUUID, Meeting) if (location.meeting !=meeting): logging.warning("Location %s is not in meeting %s." %(location.name,meeting.uuid)) else: locationLeftMeetingEvent = Event("LOCATION_LEFT_MEETING", location.uuid, None, {"meeting":meeting.uuid}) locationLeftMeetingEvent.dispatch()
def post(self): actor = self.get_current_actor() # check and see if the deassign flag is set. deassign = self.get_argument("deassign", default=None) if(deassign==None): # if deassign wasn't set, look for an assignment UUID parameter assignedTo = state.get_obj(self.get_argument("assignedToUUID"), User) p = {"taskUUID":self.get_argument("taskUUID"), "assignedTo":assignedTo.uuid, "deassign":False} else: # if deassign was set, then trigger a deassign event. p = {"taskUUID":self.get_argument("taskUUID"), "deassign":True} logging.debug("assign params: " + str(p)) assignTaskEvent = Event("ASSIGN_TASK", actor.uuid, actor.getMeeting().uuid, params = p) assignTaskEvent.dispatch()
def _handleLocationLeftMeeting(event): location = event.actor meeting = state.get_obj(event.params["meeting"], model.Meeting) meeting.locationLeft(location) if (len(meeting.locations)==0): endMeetingEvent = e.Event("END_MEETING", event.actor.uuid, None, {"meeting": meeting.uuid}) event.queue(endMeetingEvent) else: if not meeting.isNamed: title = "Meeting with " for location in meeting.locations: if location.isLoggedIn: title = title +location.name+", " title = title[0:-2] editMeetingEvent = e.Event("EDIT_MEETING", None, None, {"meeting":meeting.uuid, "title": title}) event.queue(editMeetingEvent) meeting.eventHistoryReadable.append(location.name + " left the meeting") return event