Exemple #1
0
def handle_publish_message(data, push_socket):
    message = data["message"]
    channel = data["channel"]
    author = g.user["name"]
    email = g.user["email"]
    gravatar = g.user["gravatar"]
    # we use isoformat in json because it cant handle datetime objects
    time_now = datetime.datetime.utcnow()
    mongo_event_object = {
        "author": author,
        "message": message,
        "email": email,
        "channel": channel,
        "gravatar": gravatar,
        "datetime": time_now
    }
    # db insertion adds an _id field
    db.events.insert(mongo_event_object)
    event_object = {
        "action": "publish_message",
        "data": message_dict_from_event_object(mongo_event_object),
    }
    packed = json.dumps(event_object)

    # -> Everyone
    # prepend an identifier showing which channel the event happened on for PUB/SUB
    push_socket.send(" ".join([zmq_channel_key(channel), packed]))
Exemple #2
0
def send_user_status_update(user, channel, push_socket, status):
  event_object = {
      "action": "user_" + status,
      "data": {
        "channel": channel,
        "email": user["email"],
      },
  }
  packed = g.msg_packer.pack(event_object)
  push_socket.send(" ".join([zmq_channel_key(channel), packed]))
Exemple #3
0
def send_user_status_update(user, channel, push_socket, status):
  event_object = {
      "action": "user_" + status,
      "data": {
        "channel": channel,
        "user": {
          "email": g.user["email"],
          "gravatar": g.user["gravatar"],
          "name": g.user["name"],
          "username": g.user["email"].split("@")[0],
          "status": status,
        }
      },
  }
  packed = json.dumps(event_object)
  push_socket.send(" ".join([zmq_channel_key(channel), packed]))
Exemple #4
0
def send_join_channel(channel, user, push_socket):
  channel_id = zmq_channel_key(channel)
  join_channel_event = {
      "action": "join_channel",
      "data": {
        "channel": channel,
        "user": {
          "email": user["email"],
          "gravatar": user["gravatar"],
          "name": user["name"],
          "username": user["email"].split("@")[0],
          "status": "active",
        },
      },
  }
  # alert channel subscribers to new user
  packed_join_channel = json.dumps(join_channel_event)
  push_socket.send(" ".join([channel_id, packed_join_channel]))
Exemple #5
0
def send_join_channel(channel, user, push_socket):
  channel_id = zmq_channel_key(channel)
  join_channel_event = {
      "action": "join_channel",
      "data": {
        "channel": channel,
        "user": {
          "email": user["email"],
          "gravatar": user["gravatar"],
          "name": user["name"],
          "username": user["email"].split("@")[0],
          "status": "active",
        },
      },
  }
  # alert channel subscribers to new user
  packed_join_channel = g.msg_packer.pack(join_channel_event)
  push_socket.send(" ".join([channel_id, packed_join_channel]))
Exemple #6
0
def handle_join_channel(channel, subscribe_socket, push_socket, client_id):
    add_user_to_channel(g.user, channel)
    set_user_channel_status(g.user, channel, "active")
    channel_id = zmq_channel_key(channel)

    send_join_channel(channel, g.user, push_socket)

    # subscribe to events happening on this channel
    subscribe_socket.setsockopt(zmq.SUBSCRIBE, channel_id)

    join_channel_event = {
        "action": "join_channel",
        "data": {
            "channel": channel,
            "user": {
                "email": g.user["email"],
                "gravatar": g.user["gravatar"],
                "name": g.user["name"],
                "username": g.user["email"].split("@")[0],
                "status": "active",
            },
        },
    }
    # alert channel subscribers to new user
    packed_join_channel = json.dumps(join_channel_event)
    push_socket.send(" ".join([channel_id, packed_join_channel]))

    # alert the user's other open clients of the change
    self_join_channel_event = {
        "action": "self_join_channel",
        "data": {
            "client_id": client_id,
            "channel": channel,
            "channel_id": channel_id,
        },
    }
    packed_self_join_channel = json.dumps(self_join_channel_event)
    push_socket.send(" ".join([str(g.user["email"]),
                               packed_self_join_channel]))
Exemple #7
0
def handle_join_channel(channel, subscribe_socket, push_socket, client_id):
  add_user_to_channel(g.user, channel)
  set_user_channel_status(g.user, channel, "active")
  channel_id = zmq_channel_key(channel)

  send_join_channel(channel, g.user, push_socket)

  # subscribe to events happening on this channel
  subscribe_socket.setsockopt(zmq.SUBSCRIBE, channel_id)

  join_channel_event = {
      "action": "join_channel",
      "data": {
        "channel": channel,
        "user": {
          "email": g.user["email"],
          "gravatar": g.user["gravatar"],
          "name": g.user["name"],
          "username": g.user["email"].split("@")[0],
          "status": "active",
        },
      },
  }
  # alert channel subscribers to new user
  packed_join_channel = json.dumps(join_channel_event)
  push_socket.send(" ".join([channel_id, packed_join_channel]))

  # alert the user's other open clients of the change
  self_join_channel_event = {
      "action": "self_join_channel",
      "data": {
        "client_id": client_id,
        "channel": channel,
        "channel_id": channel_id,
      },
  }
  packed_self_join_channel = json.dumps(self_join_channel_event)
  push_socket.send(" ".join([str(g.user["email"]), packed_self_join_channel]))
Exemple #8
0
def handle_publish_message(data, push_socket):
  message = data["message"]
  channel = data["channel"]
  author = g.user["name"]
  email = g.user["email"]
  gravatar = g.user["gravatar"]
  # we use isoformat in json because it cant handle datetime objects
  time_now = datetime.datetime.utcnow()
  mongo_event_object = { "author": author,
                         "message": message,
                         "email": email,
                         "channel": channel,
                         "gravatar": gravatar,
                         "datetime": time_now }
  # db insertion adds an _id field
  db.events.insert(mongo_event_object)
  event_object = { "action":"publish_message",
                   "data": message_dict_from_event_object(mongo_event_object),
                 }
  packed = json.dumps(event_object)

  # -> Everyone
  # prepend an identifier showing which channel the event happened on for PUB/SUB
  push_socket.send(" ".join([zmq_channel_key(channel), packed]))
Exemple #9
0
def eventhub_client():
  websocket = request.environ.get('wsgi.websocket')
  if not websocket:
    return
  push_socket = zmq_context.socket(zmq.PUSH)
  push_socket.connect(current_app.config["PUSH_ADDRESS"])
  subscribe_socket = zmq_context.socket(zmq.SUB)
  client_id = str(uuid.uuid4())

  subscribe_socket.connect(current_app.config["SUBSCRIBE_ADDRESS"])

  # add yourself to your current pool of open clients
  add_to_user_clients(g.user, client_id)

  # listen for messages that happen on channels the user is subscribed to
  for channel in g.user["channels"]:
    channel_id = zmq_channel_key(channel)
    subscribe_socket.setsockopt(zmq.SUBSCRIBE, channel_id)

    # if redis was cleared, we'll need to resend the join channel event to populate the user status of open
    # clients
    channel_status = get_user_channel_status(g.user, channel)
    if channel_status is None:
      send_join_channel(channel, g.user, push_socket)

    set_user_channel_status(g.user, channel, "active")
    send_user_status_update(g.user, channel, push_socket, "active")

  # subscribe to events the user triggered that could affect the user's other open clients
  subscribe_socket.setsockopt(zmq.SUBSCRIBE, str(g.user["email"]))

  poller = zmq.Poller()
  poller.register(subscribe_socket, zmq.POLLIN)
  poller.register(websocket.socket, zmq.POLLIN)

  try:
    message = None
    while True:
      events = dict(poller.poll())

      # Server -> Client
      if subscribe_socket in events:
        message = subscribe_socket.recv()

        # the message is prepended by the channel_id (for PUB/SUB reasons)
        channel_id, packed = message.split(" ", 1)

        unpacked = json.loads(packed)

        action = unpacked["action"]
        if action in ["publish_message", "join_channel", "leave_channel", "user_active", "user_offline"]:
          websocket.send(packed)
        elif action in ["self_join_channel", "self_leave_channel"]:
          event_type = action.split("_")[1]
          handle_self_channel_event(client_id, websocket, subscribe_socket, unpacked["data"], event_type)

      # Client -> Server
      if websocket.socket.fileno() in events:
        socket_data = websocket.receive()
        if socket_data is None:
          break
        socket_data = json.loads(socket_data)
        action = socket_data["action"]
        data = socket_data["data"]
        if action == "switch_channel":
          handle_switch_channel(data["channel"])
        elif action == "publish_message":
          handle_publish_message(data, push_socket)
        elif action == "preview_message":
          handle_preview_message(data, websocket)
        elif action == "join_channel":
          handle_join_channel(data["channel"], subscribe_socket, push_socket, client_id)
        elif action == "leave_channel":
          handle_leave_channel(data["channel"], subscribe_socket, push_socket, client_id)
        elif action == "reorder_channels":
          handle_reorder_channels(data["channels"], push_socket, client_id)
        elif action == "ping":
          handle_ping(websocket, push_socket, client_id)
  except geventwebsocket.WebSocketError, e:
    print "{0} {1}".format(e.__class__.__name__, e)
Exemple #10
0
def send_user_status_update(user, channel, push_socket, status):
  packed = json_user_status_event_object(user, channel, status)
  push_socket.send(" ".join([zmq_channel_key(channel), packed]))
Exemple #11
0
def eventhub_client():
  if not request.environ.get('wsgi.websocket'):
    return ""
  websocket = request.environ['wsgi.websocket']
  push_socket = zmq_context.socket(zmq.PUSH)
  push_socket.connect(current_app.config["PUSH_ADDRESS"])
  subscribe_socket = zmq_context.socket(zmq.SUB)
  client_id = str(uuid.uuid4())

  subscribe_socket.connect(current_app.config["SUBSCRIBE_ADDRESS"])

  # add yourself to your current pool of open clients
  add_to_user_clients(g.user, client_id)

  # listen for messages that happen on channels the user is subscribed to
  for channel in g.user["channels"]:
    channel_id = zmq_channel_key(channel)
    subscribe_socket.setsockopt(zmq.SUBSCRIBE, channel_id)

    # if redis was cleared, we'll need to resend the join channel event to populate the user status of open
    # clients
    channel_status = get_user_channel_status(g.user, channel)
    if channel_status is None:
      send_join_channel(channel, g.user, push_socket)

    set_user_channel_status(g.user, channel, "active")
    send_user_status_update(g.user, channel, push_socket, "active")

  # subscribe to events the user triggered that could affect the user's other open clients
  subscribe_socket.setsockopt(zmq.SUBSCRIBE, str(g.user["email"]))

  poller = zmq.Poller()
  poller.register(subscribe_socket, zmq.POLLIN)
  poller.register(websocket.socket, zmq.POLLIN)

  try:
    message = None
    while True:
      events = dict(poller.poll())

      # Server -> Client
      if subscribe_socket in events:
        message = subscribe_socket.recv()

        # the message is prepended by the channel_id (for PUB/SUB reasons)
        channel_id, packed = message.split(" ", 1)
        g.msg_unpacker.feed(packed)
        unpacked = g.msg_unpacker.unpack()
        action = unpacked["action"]
        if action in ["publish_message", "join_channel", "leave_channel", "user_active", "user_offline"]:
          websocket.send(json.dumps(unpacked))
        elif action in ["self_join_channel", "self_leave_channel", "self_reorder_channels"]:
          event_type = action.split("_")[1]
          handle_self_channel_event(client_id, websocket, subscribe_socket, unpacked["data"], event_type)

      # Client -> Server
      if websocket.socket.fileno() in events:
        socket_data = websocket.receive()
        if socket_data is None:
          break
        socket_data = json.loads(socket_data)
        action = socket_data["action"]
        data = socket_data["data"]
        if action == "switch_channel":
          handle_switch_channel(data["channel"])
        elif action == "publish_message":
          handle_publish_message(data, push_socket)
        elif action == "preview_message":
          handle_preview_message(data, websocket)
        elif action == "join_channel":
          handle_join_channel(data["channel"], subscribe_socket, push_socket, client_id)
        elif action == "leave_channel":
          handle_leave_channel(data["channel"], subscribe_socket, push_socket, client_id)
        elif action == "reorder_channels":
          handle_reorder_channels(data["channels"], push_socket, client_id)
  except geventwebsocket.WebSocketError, e:
    print "{0} {1}".format(e.__class__.__name__, e)
Exemple #12
0
def send_user_status_update(user, channel, push_socket, status):
    packed = json_user_status_event_object(user, channel, status)
    push_socket.send(" ".join([zmq_channel_key(channel), packed]))