Index: binaries/data/mods/public/gui/lobby/lobby.js =================================================================== --- binaries/data/mods/public/gui/lobby/lobby.js +++ binaries/data/mods/public/gui/lobby/lobby.js @@ -128,9 +128,98 @@ var g_AskedReconnect = false; /** + * These functions handle messages sent to this user directly, i.e. not through the multi-user-chat room. + */ +var g_MessageHandlers = { + "Chat": msg => { + // We intend to not support private messages between users + if (msg.from && Engine.LobbyGetPlayerRole(msg.from) != "moderator") + return; + // some XMPP clients send trailing whitespace + addChatMessage({ + "from": escapeText(msg.from || "system"), + "text": escapeText(msg.body.trim()), + "time": msg.time, + "private": true, + "historic": msg.historic + }); + }, + "Error": msg => { + addChatMessage({ + "from": "system", + "text": escapeText(msg.body), + "time": msg.time, + "historic": msg.historic + }); + }, + "Groupchat": msg => { + error("Unexpected groupchat message: " + uneval(msg)) + }, + "Headline": msg => { + // Announcement or message of the day + addChatMessage({ + "from": escapeText(msg.from || "system"), + "text": escapeText(msg.subject.trim()) + "\n" + escapeText(msg.body.trim()), + "time": msg.time, + "historic": msg.historic + }); + + if (!msg.historic) + messageBox( + 400, 250, + msg.body.trim(), + msg.subject.trim()); + }, + "Normal": msg => { + warn("Normal message not implemented: " + uneval(msg)); + } +}; + +/** + * These functions handle messages sent through the multi-user-chat room. + */ +var g_MUCRoomMessageHandlers = { + "Chat": msg => { + // We intend to not support private messages between users + if (msg.private && (msg.from && Engine.LobbyGetPlayerRole(msg.from) != "moderator")) + return; + + addChatMessage({ + "from": escapeText(msg.from), + "text": escapeText(msg.body), + "time": msg.times, + "private": msg.private, + "historic": msg.historic + }); + }, + "Error": msg => { + addChatMessage({ + "from": "system", + "text": escapeText(msg.tex), + "time": msg.time, + "historic": msg.historic + }); + }, + "Groupchat": msg => { + addChatMessage({ + "from": escapeText(msg.from), + "text": escapeText(msg.body), + "time": msg.time, + "historic": msg.historic + }); + }, + "Headline": msg => { + warn("Headline muc room message not implemented: " + uneval(msg)); + }, + "Normal": msg => { + // gloox receives an empty message of this type if the banlist changed + if (msg.subject || msg.body) + warn("Normal muc message not implemented: " + uneval(msg)); + } +}; + +/** * Processing of notifications sent by XmppClient.cpp. - * - * @returns true if the playerlist GUI must be updated. */ var g_NetMessageTypes = { "system": { @@ -247,32 +336,17 @@ "banned": msg => { handleKick(true, msg.nick, msg.reason, msg.time, msg.historic); }, - "room-message": msg => { - addChatMessage({ - "from": escapeText(msg.from), - "text": escapeText(msg.text), - "time": msg.time, - "historic": msg.historic - }); + "muc-message": msg => { + if (g_MUCRoomMessageHandlers[msg.subtype]) + g_MUCRoomMessageHandlers[msg.subtype](msg); + else + error("Received invalid MUC message: " + uneval(msg)); }, - "private-message": msg => { - // Announcements and the Message of the Day are sent by the server directly - if (!msg.from) - messageBox( - 400, 250, - msg.text.trim(), - translate("Notice")); - - // We intend to not support private messages between users - if (!msg.from || Engine.LobbyGetPlayerRole(msg.from) == "moderator") - // some XMPP clients send trailing whitespace - addChatMessage({ - "from": escapeText(msg.from || "system"), - "text": escapeText(msg.text.trim()), - "time": msg.time, - "historic": msg.historic, - "private": true - }); + "message": msg => { + if (g_MessageHandlers[msg.subtype]) + g_MessageHandlers[msg.subtype](msg); + else + error("Received invalid message: " + uneval(msg)); } }, "game": { Index: source/lobby/XmppClient.h =================================================================== --- source/lobby/XmppClient.h +++ source/lobby/XmppClient.h @@ -104,6 +104,7 @@ */ static const char* GetPresenceString(const gloox::Presence::PresenceType presenceType); static const char* GetRoleString(const gloox::MUCRoomRole role); + static const char* MessageSubtypeToString(gloox::Message::MessageType err); static std::string StanzaErrorToString(gloox::StanzaError err); static std::string RegistrationResultToString(gloox::RegistrationResult res); static std::string ConnectionErrorToString(gloox::ConnectionError err); Index: source/lobby/XmppClient.cpp =================================================================== --- source/lobby/XmppClient.cpp +++ source/lobby/XmppClient.cpp @@ -745,30 +745,45 @@ */ void XmppClient::handleMUCMessage(glooxwrapper::MUCRoom& UNUSED(room), const glooxwrapper::Message& msg, bool priv) { - DbgXMPP(msg.from().resource() << " said " << msg.body()); + DbgXMPP( + "handleMUCMessage " + "Subtype: " << MessageSubtypeToString(msg.subtype()) << ", " + "From: " << msg.from().resource() << ", " + "Subject: " << msg.subject() << ", " + "Body: " << msg.body() << ", " + "Private: " << (priv ? "true" : "false")); CreateGUIMessage( "chat", - priv ? "private-message" : "room-message", + "muc-message", ComputeTimestamp(msg), + "subtype", msg.subtype(), + "private", priv, "from", msg.from().resource(), - "text", msg.body()); + "subject", msg.subject(), + "body", msg.body()); } /** - * Handle a private message. + * Handle a message sent to the user. */ void XmppClient::handleMessage(const glooxwrapper::Message& msg, glooxwrapper::MessageSession*) { - DbgXMPP("type " << msg.subtype() << ", subject " << msg.subject() - << ", message " << msg.body() << ", thread id " << msg.thread()); + DbgXMPP( + "handleMessage " + "Subtype: " << MessageSubtypeToString(msg.subtype()) << ", " + "From: " << msg.from().username() << ", " + "Subject:" << msg.subject() << ", " + "Body:" << msg.body()); CreateGUIMessage( "chat", - "private-message", + "message", ComputeTimestamp(msg), - "from", msg.from().resource(), - "text", msg.body()); + "subtype", msg.subtype(), + "from", msg.from().username(), + "subject", msg.subject(), + "body", msg.body()); } /** @@ -984,6 +999,8 @@ */ void XmppClient::handleMUCSubject(glooxwrapper::MUCRoom& UNUSED(room), const glooxwrapper::string& nick, const glooxwrapper::string& subject) { + DbgXMPP("Lobby subject changed to " << subject); + m_Subject = wstring_from_utf8(subject.to_string()); CreateGUIMessage( @@ -1297,6 +1314,22 @@ #undef CASE } +const char* XmppClient::MessageSubtypeToString(gloox::Message::MessageType messageType) +{ +#define CASE(X) case gloox::Message::MessageType::X: return #X; + switch (messageType) + { + CASE(Chat) + CASE(Error) + CASE(Groupchat) + CASE(Headline) + CASE(Normal) + default: + return "invalid"; + } +#undef CASE +} + void XmppClient::SendStunEndpointToHost(const StunClient::StunEndpoint& stunEndpoint, const std::string& hostJIDStr) { DbgXMPP("SendStunEndpointToHost " << hostJIDStr); Index: source/lobby/scripting/GlooxScriptConversions.cpp =================================================================== --- source/lobby/scripting/GlooxScriptConversions.cpp +++ source/lobby/scripting/GlooxScriptConversions.cpp @@ -38,6 +38,12 @@ ToJSVal(cx, ret, XmppClient::GetRoleString(val)); } +template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::MutableHandleValue ret, const gloox::Message::MessageType& val) +{ + // Avoid unneeded std::string() and wstring_from_utf8() + ToJSVal(cx, ret, XmppClient::MessageSubtypeToString(val)); +} + template<> void ScriptInterface::ToJSVal(JSContext* cx, JS::MutableHandleValue ret, const gloox::StanzaError& val) { ToJSVal(cx, ret, wstring_from_utf8(XmppClient::StanzaErrorToString(val)));