Have you ever tried to use QuickBlox to add chat to your products? Were you surprised that message objects returned from different API calls could have wildly different object models?

Boy, I sure was. And it surprised me enough, I figured I'd blog about it. Because that's what tech bloggers do.

Here's one message I received from a QB.chat.message.list call:

{
    "_id": "mfn5e1400e30fe1f3400000a",
    "attachments": [],
    "chat_dialog_id": "mfn388d1f9af994169000010",
    "created_at": "2017-02-28T20:44:47Z",
    "date_sent": 1488314687,
    "delivered_ids": [
        1115,
        1116
    ],
    "message": "asdfasdf",
    "read_ids": [
        1115,
        1116
    ],
    "recipient_id": 1116,
    "sender_id": 1115,
    "updated_at": "2017-02-28T20:47:30Z",
    "read": 1
}

And now here's a different message pulled in from an event handler listening to QB.chat.onMessageListener:

(Aside: Looking back, I really enjoy how much time I see I put into making sure the message bodies reflect real-world message contents.)

{
    "id": "mfn5e21b0e30fe1f3400000b",
    "dialog_id": "mfn388d1f9af994169000010",
    "recipient_id": null,
    "type": "chat",
    "body": "sdfgsdgkf",
    "extension": {
        "save_to_history": "1",
        "message_id": "mfn5e21b0e30fe1f3400000b",
        "dialog_id": "mfn388d1f9af994169000010",
        "date_sent": "1488314907"
    },
    "delay": null,
    "markable": 1
}

Huh? Let's see if we can match any of these up to close relatives...

message.list messages

onMessageListener messages

_id

id AND extension.message_id

attachments

Maybe on demand?

chat_dialogId

dialog_id AND extension.dialog_id

date_sent

extension.date_sent

message

body <<< this is pretty inexcusable

recipient_id

recipient_id <<< Much rejoicing!

read

markable (?)

created_at

????

delivered_ids

????

read_ids

????

sender_id

????
Though note onMessageListener's signature is function (userId, msg)

updated_at

????

????

type

????

extension.save_to_history

????

delay

What is the world is going on there?

I've taken to wrapping QB with a QB Extensions singleton of a ton of convenience classes to access dialogs and messages, and those convenience methods add properties to make sure the objects map up a little better, so I'm adding stuff like...

msg.XSenderId = userId;
msg.XDateSent = parseDateSent(msg.extension.date_sent);
msg.XSenderHandle = getUserHandle(userId);
msg.XDialogId = msg.type === "chat"
    ? userId
    : msg.dialog_id;
msg.XDialogId = msg.XDialogId.toString();

// these are also extensions, but I'm just going to normalize on the
// property names you'd get back from a call to `QB.chat.message.list`.
msg.message = msg.body;
msg._id = msg.id; 

I'm not super happy with all these kludges, but it makes accessing and displaying objects downstream a lot DRYer.

(Note: Dialogs are similarly variable in their object models, depending on where you get them from. /sigh)

Labels: , ,