def leave_room(self, room, event_only=False): from flask.globals import current_app from flask_socketio import leave_room from slurk.extensions.events import socketio if self in room.users and not event_only: room.users.remove(self) current_app.session.commit() if self.session_id is not None: Log.add("leave", self, room) socketio.emit( "left_room", { "room": room.id, "user": self.id, }, room=self.session_id, ) leave_room(str(room.id), self.session_id, "/") socketio.emit( "status", dict( type="leave", user=dict(id=self.id, name=self.name), room=room.id, timestamp=str(datetime.utcnow()), ), room=str(room.id), )
def room_created(payload): db = current_app.session room = db.query(Room).get(payload["room"]) if "room" in payload else None task = db.query(Task).get(payload["task"]) if "task" in payload else None if "room" not in payload: False, 'Missing argument "room"' if not room: return False, f'User "{room}" does not exist' if "task" in payload and task is None: return False, f'Task "{task}" does not exist' socketio.emit("new_room", {"room": room.id}, broadcast=True) if task is not None: users = [] for user in room.users: users.append({"id": user.id, "name": user.name}) socketio.emit( "new_task_room", { "room": room.id, "task": task.id, "users": users }, broadcast=True, ) return True
def mouse(payload): current_user_id = current_user.get_id() if not current_user_id: return False, "invalid session id" user = dict(id=current_user_id, name=current_user.name) db = current_app.session room = db.query(Room).get(payload["room"]) if "room" in payload else None if room is None: return False, "Room not found" data = dict( type=payload.get("type"), coordinates=payload.get("coordinates"), element_id=payload.get("element_id"), ) socketio.emit( "mouse", dict( user=user, room=room.id, timestamp=str(datetime.utcnow()), **data, ), room=str(room.id), ) Log.add(event="mouse", user=current_user, room=room, data=data)
def bounding_box(payload): if "room" not in payload: return False, 'missing argument: "room"' db = current_app.session room = db.query(Room).get(payload.pop("room")) if not room: return False, "Room not found" if current_user not in room.users: return False, "User not in this room" if "type" not in payload: return False, "Missing type" if payload["type"] == "add" and "coordinates" not in payload: return False, "Missing coordinates" Log.add(event="bounding_box", user=current_user, room=room, data=payload) user = {"id": current_user.get_id(), "name": current_user.name} for usr in room.users: if usr.token.permissions.receive_bounding_box and usr.session_id: socketio.emit( "bounding_box", { "user": user, "room": room.id, **payload }, room=usr.session_id, )
def delete(self, *, room, id, **kwargs): """Remove a class from an element identified by it's ID""" kwargs["id"] = id receiver_id = kwargs.pop("receiver_id", None) receiver, target = get_receiver_target(receiver_id, str(room.id)) Log.add("class_remove", room=room, receiver=receiver, data=kwargs) socketio.emit("class_remove", kwargs, room=target) return kwargs
def patch(self, *, room, id, **kwargs): """Update the text of an element identified by it's ID""" kwargs["id"] = id receiver_id = kwargs.pop("receiver_id", None) receiver, target = get_receiver_target(receiver_id, str(room.id)) Log.add("set_text", room=room, receiver=receiver, data=kwargs) socketio.emit("text_update", kwargs, room=target) return kwargs
def patch(self, *, room, element, **kwargs): """Update an element identified by it's type""" kwargs["element"] = element receiver_id = kwargs.pop("receiver_id", None) receiver, target = get_receiver_target(receiver_id, str(room.id)) Log.add("set_attribute", room=room, receiver=receiver, data=kwargs) socketio.emit("attribute_update", kwargs, room=target) return kwargs
def joined(): socketio.emit( "status", dict( type="join", user=user, room=room_id, timestamp=str(datetime.utcnow()), ), room=str(room_id), )
def patch(self, *, user, id, **kwargs): """Update the text of an element identified by it's ID""" kwargs["id"] = id Log.add("set_text", user=user, data=kwargs) if user.session_id is None: abort( HTTPStatus.UNPROCESSABLE_ENTITY, query={ "user_id": f"User `{user.id} does not have a session id associated" }, ) socketio.emit("text_update", kwargs, room=str(user.session_id)) return kwargs
def patch(self, *, user, element, **kwargs): """Update an element identified by it's type""" kwargs["element"] = element Log.add("set_attribute", user=user, data=kwargs) if user.session_id is None: abort( HTTPStatus.UNPROCESSABLE_ENTITY, query={ "user_id": f"User `{user.id} does not have a session id associated" }, ) socketio.emit("attribute_update", kwargs, room=user.session_id) return kwargs
def delete(self, *, user, id, **kwargs): """Remove a class from an element identified by it's ID""" kwargs["id"] = id Log.add("class_remove", user=user, data=kwargs) if user.session_id is None: abort( HTTPStatus.UNPROCESSABLE_ENTITY, query={ "user_id": f"User `{user.id} does not have a session id associated" }, ) socketio.emit("class_remove", kwargs, room=str(user.session_id)) return kwargs
def post_connection(retry=True): response = current_app.openvidu.post_connection( room.openvidu_session_id, json=dict( role=self.token.permissions.openvidu_role, kurentoOptions=dict( videoMaxRecvBandwidth=ov_property( "video_max_recv_bandwidth"), videoMinRecvBandwidth=ov_property( "video_min_recv_bandwidth"), videoMaxSendBandwidth=ov_property( "video_max_send_bandwidth"), videoMinSendBandwidth=ov_property( "video_min_send_bandwidth"), allowedFilters=ov_property("allowed_filters"), ), ), ) if response.status_code == 200: socketio.emit( "openvidu", dict( connection=WebRtcConnectionSchema.Response(). dump(response.json()), start_with_audio=ov_property( "start_with_audio"), start_with_video=ov_property( "start_with_video"), video_resolution=ov_property( "video_resolution"), video_framerate=ov_property("video_framerate"), video_publisher_location=ov_property( "video_publisher_location"), video_subscribers_location=ov_property( "video_subscribers_location"), ), room=self.session_id, ) elif response.status_code == 404: json = room.session.parameters json["customSessionId"] = room.session.id response = current_app.openvidu.post_session(json) if response.status_code == 200: post_connection(retry=False) else: current_app.logger.error( response.json().get("message")) else: current_app.logger.error( response.json().get("message"))
def keypress(message): typing = message.get("typing", None) if typing is None: return current_user_id = current_user.get_id() if not current_user_id: return for room in current_user.rooms: user = { "id": current_user_id, "name": current_user.name, } if typing: socketio.emit("start_typing", {"user": user}, room=str(room.id)) else: socketio.emit("stop_typing", {"user": user}, room=str(room.id))
def typed_message(payload): """ This function handles live-typing mode. It is called when 'typed_message' event is fired and broadcasts the current message that the user typed to the room through 'user_message' event. """ current_user_id = current_user.get_id() if not current_user_id: return for room in current_user.rooms: user = { "id": current_user_id, "name": current_user.name, } socketio.emit( "user_message", { "user": user, "message": payload["message"] }, room=str(room.id), )
def patch(self, *, room, cls, **kwargs): """Update an element identified by it's class""" kwargs["cls"] = cls Log.add("set_attribute", room=room, data=kwargs) socketio.emit("attribute_update", kwargs, room=str(room.id)) return kwargs
def patch(self, *, room, id, **kwargs): """Update the text of an element identified by it's ID""" kwargs["id"] = id Log.add("set_text", room=room, data=kwargs) socketio.emit("text_update", kwargs, room=str(room.id)) return kwargs
def patch(self, *, room, element, **kwargs): """Update an element identified by it's type""" kwargs["element"] = element Log.add("set_attribute", room=room, data=kwargs) socketio.emit("attribute_update", kwargs, room=str(room.id)) return kwargs
def emit_message(event, payload, data): if "room" not in payload: return False, 'missing argument: "room"' db = current_app.session room = db.query(Room).get(payload["room"]) if not room: return False, "Room not found" broadcast = data["broadcast"] = payload.get("broadcast", False) if broadcast: if not current_user.token.permissions.broadcast: return False, "You are not allowed to broadcast" target = None private = False else: if "receiver_id" in payload: if not current_user.token.permissions.send_privately: return False, "You are not allowed to send privately" receiver_id = payload["receiver_id"] receiver = db.query(User).get(receiver_id) if not receiver: return False, f'User "{receiver_id}" does not exist' if not receiver.session_id: return False, f'User "{receiver_id}" is not logged in' if room not in receiver.rooms: return False, f'User "{receiver_id}" is not in this room' target = receiver.session_id private = True else: if current_user not in room.users: return False, "Not in room" if room.layout.read_only or room.read_only: return False, f"Room {room.id} is read-only" target = str(room.id) private = False user = dict(id=current_user.get_id(), name=current_user.name) socketio.emit( event, dict( user=user, room=room.id if room else None, timestamp=str(datetime.utcnow()), private=private, **data, ), room=target, broadcast=broadcast, ) Log.add( event=event, user=current_user, room=room, receiver=receiver if private and not broadcast else None, data=data, ) for room in current_user.rooms: socketio.emit("stop_typing", {"user": user}, room=str(room.id)) return True
def join_room(self, room): from flask.globals import current_app from flask_socketio import join_room from slurk.views.api.openvidu.schemas import WebRtcConnectionSchema from slurk.extensions.events import socketio if self not in room.users: room.users.append(self) current_app.session.commit() if self.session_id is not None: join_room(str(room.id), self.session_id, "/") user = dict(id=self.id, name=self.name) room_id = room.id def joined(): socketio.emit( "status", dict( type="join", user=user, room=room_id, timestamp=str(datetime.utcnow()), ), room=str(room_id), ) socketio.emit( "joined_room", { "room": room.id, "user": self.id, }, room=self.session_id, callback=joined, ) Log.add("join", self, room) # Create an OpenVidu connection if apropiate if (hasattr(current_app, "openvidu") and room.openvidu_session_id and self.token.permissions.openvidu_role): def ov_property(name): if name in self.token.openvidu_settings: return self.token.openvidu_settings[name] else: return room.layout.openvidu_settings[name] # OpenVidu destroys a session when everyone left. # This ensures, that the session is persistant by recreating the session def post_connection(retry=True): response = current_app.openvidu.post_connection( room.openvidu_session_id, json=dict( role=self.token.permissions.openvidu_role, kurentoOptions=dict( videoMaxRecvBandwidth=ov_property( "video_max_recv_bandwidth"), videoMinRecvBandwidth=ov_property( "video_min_recv_bandwidth"), videoMaxSendBandwidth=ov_property( "video_max_send_bandwidth"), videoMinSendBandwidth=ov_property( "video_min_send_bandwidth"), allowedFilters=ov_property("allowed_filters"), ), ), ) if response.status_code == 200: socketio.emit( "openvidu", dict( connection=WebRtcConnectionSchema.Response(). dump(response.json()), start_with_audio=ov_property( "start_with_audio"), start_with_video=ov_property( "start_with_video"), video_resolution=ov_property( "video_resolution"), video_framerate=ov_property("video_framerate"), video_publisher_location=ov_property( "video_publisher_location"), video_subscribers_location=ov_property( "video_subscribers_location"), ), room=self.session_id, ) elif response.status_code == 404: json = room.session.parameters json["customSessionId"] = room.session.id response = current_app.openvidu.post_session(json) if response.status_code == 200: post_connection(retry=False) else: current_app.logger.error( response.json().get("message")) else: current_app.logger.error( response.json().get("message")) post_connection()
def post(self, *, room, id, **kwargs): """Add a class to an element identified by it's ID""" kwargs["id"] = id Log.add("class_add", room=room, data=kwargs) socketio.emit("class_add", kwargs, room=str(room.id)) return kwargs
def delete(self, *, room, id, **kwargs): """Remove a class from an element identified by it's ID""" kwargs["id"] = id Log.add("class_remove", room=room, data=kwargs) socketio.emit("class_remove", kwargs, room=str(room.id)) return kwargs