summaryrefslogtreecommitdiff
path: root/protocols/WhatsApp/src
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2022-11-03 14:37:59 +0300
committerGeorge Hazan <ghazan@miranda.im>2022-11-03 14:38:09 +0300
commit3b2edeff1b7d1bff60174467d3d1cabefa5aa000 (patch)
treebbfddcc033ab58b6d3aceaddc425abfbf467ade0 /protocols/WhatsApp/src
parent6d54b6628f29f9d600c1afb9f520899890b41fbd (diff)
WhatsApp: initial commit of group chats - non-cached, nothing but reading groupchat metadata
Diffstat (limited to 'protocols/WhatsApp/src')
-rw-r--r--protocols/WhatsApp/src/appsync.cpp6
-rw-r--r--protocols/WhatsApp/src/chats.cpp139
-rw-r--r--protocols/WhatsApp/src/message.cpp13
-rw-r--r--protocols/WhatsApp/src/proto.h6
-rw-r--r--protocols/WhatsApp/src/server.cpp4
-rw-r--r--protocols/WhatsApp/src/utils.cpp12
6 files changed, 106 insertions, 74 deletions
diff --git a/protocols/WhatsApp/src/appsync.cpp b/protocols/WhatsApp/src/appsync.cpp
index 2032a928ec..36531a5179 100644
--- a/protocols/WhatsApp/src/appsync.cpp
+++ b/protocols/WhatsApp/src/appsync.cpp
@@ -141,9 +141,6 @@ void WhatsAppProto::OnIqServerSync(const WANode &node)
}
}
- CMStringA szSetting(FORMAT, "Collection_%s", pszName);
- // setDword(szSetting, dwVersion);
-
JSONNode jsonRoot, jsonMap;
for (auto &it : pCollection->indexValueMap)
jsonMap << CHAR_PARAM(ptrA(mir_base64_encode(it.first.c_str(), it.first.size())), ptrA(mir_base64_encode(it.second.c_str(), it.second.size())));
@@ -221,8 +218,7 @@ void WhatsAppProto::ApplyPatch(const JSONNode &index, const Wa__SyncActionValue
auto title = index.at((json_index_t)0).as_string();
if (title == "contact" && data->contactaction) {
- WAJid jid(index.at(1).as_string().c_str());
- auto *pUser = AddUser(jid.toString(), false, jid.isGroup());
+ auto *pUser = AddUser(index.at(1).as_string().c_str(), false);
auto *pAction = data->contactaction;
auto &fullName = pAction->fullname;
diff --git a/protocols/WhatsApp/src/chats.cpp b/protocols/WhatsApp/src/chats.cpp
index 6ebb94073f..8861693fca 100644
--- a/protocols/WhatsApp/src/chats.cpp
+++ b/protocols/WhatsApp/src/chats.cpp
@@ -7,77 +7,112 @@ Copyright © 2019-22 George Hazan
#include "stdafx.h"
-void WhatsAppProto::InitChat(WAUser *pUser)
+void WhatsAppProto::GC_Init(WAUser *pUser)
{
- CMStringA jid = "";
- CMStringW wszId(Utf2T(jid.c_str())), wszNick(Utf2T(""));
+ CMStringW wszId(Utf2T(pUser->szId));
- setWString(pUser->hContact, "Nick", wszNick);
-
- pUser->si = Chat_NewSession(GCW_CHATROOM, m_szModuleName, wszId, wszNick);
+ pUser->si = Chat_NewSession(GCW_CHATROOM, m_szModuleName, wszId, getMStringW(pUser->hContact, "Nick"));
Chat_AddGroup(pUser->si, TranslateT("Owner"));
Chat_AddGroup(pUser->si, TranslateT("SuperAdmin"));
Chat_AddGroup(pUser->si, TranslateT("Admin"));
Chat_AddGroup(pUser->si, TranslateT("Participant"));
- Chat_Control(m_szModuleName, wszId, m_bHideGroupchats ? WINDOW_HIDDEN : SESSION_INITDONE);
- Chat_Control(m_szModuleName, wszId, SESSION_ONLINE);
-
- if (!pUser->bInited) {
- // CMStringA query(FORMAT, "[\"query\",\"GroupMetadata\",\"%s\"]", jid.c_str());
- // WSSend(query, &WhatsAppProto::OnGetChatInfo, pUser);
+ if (pUser->bInited) {
+ Chat_Control(m_szModuleName, wszId, m_bHideGroupchats ? WINDOW_HIDDEN : SESSION_INITDONE);
+ Chat_Control(m_szModuleName, wszId, SESSION_ONLINE);
}
+ else GC_GetMetadata(pUser->szId);
}
-void WhatsAppProto::OnGetChatInfo(const JSONNode &root, void *param)
+void WhatsAppProto::GC_GetMetadata(const char *szId)
{
- auto *pChatUser = (WAUser *)param;
- pChatUser->bInited = true;
-
- CMStringW wszOwner(root["owner"].as_mstring()), wszNick;
-
- for (auto &it : root["participants"]) {
- CMStringW jid(it["id"].as_mstring());
- CMStringA szJid(jid);
-
- GCEVENT gce = { m_szModuleName, 0, GC_EVENT_JOIN };
- gce.pszID.w = pChatUser->si->ptszID;
- gce.pszUID.w = jid;
- gce.bIsMe = (szJid == m_szJid);
+ WANodeIq iq(IQ::GET, "w:g2", szId);
+ iq.addChild("query")->addAttr("request", "interactive");
+ WSSendNode(iq, &WhatsAppProto::OnIqGcMetadata);
+}
- if (jid == wszOwner)
- gce.pszStatus.w = L"Owner";
- else if (it["isSuperAdmin"].as_bool())
- gce.pszStatus.w = L"SuperAdmin";
- else if (it["isAdmin"].as_bool())
- gce.pszStatus.w = L"Admin";
- else
- gce.pszStatus.w = L"Participant";
-
- if (gce.bIsMe)
- wszNick = getMStringW(DBKEY_NICK);
- else if (auto *pUser = FindUser(szJid))
- wszNick = Clist_GetContactDisplayName(pUser->hContact);
- else {
- int iPos = jid.Find('@');
- wszNick = (iPos != -1) ? jid.Left(iPos - 1) : jid;
+void WhatsAppProto::OnIqGcMetadata(const WANode &node)
+{
+ auto *pGroup = node.getChild("group");
+ auto *pChatUser = FindUser(node.getAttr("from"));
+ if (pChatUser == nullptr || pGroup == nullptr)
+ return;
+
+ CMStringA szOwner(pGroup->getAttr("creator")), szNick, szRole;
+
+ for (auto &it : pGroup->getChildren()) {
+ if (it->title == "description") {
+ CMStringA szDescr = it->getBody();
+ if (!szDescr.IsEmpty()) {
+ GCEVENT gce = {m_szModuleName, 0, GC_EVENT_INFORMATION};
+ gce.dwFlags = GCEF_UTF8;
+ gce.pszID.a = pChatUser->szId;
+ gce.pszText.a = szDescr.c_str();
+ Chat_Event(&gce);
+ }
+ }
+ else if (it->title == "member_add_mode") {
+ szRole = it->getBody();
+ }
+ else if (it->title == "participant") {
+ auto *jid = it->getAttr("jid");
+
+ // if role isn't specified, use the default one
+ auto *role = it->getAttr("type");
+ if (role == nullptr)
+ role = szRole;
+
+ GCEVENT gce = {m_szModuleName, 0, GC_EVENT_JOIN};
+ gce.dwFlags = GCEF_UTF8;
+ gce.pszID.a = pChatUser->szId;
+ gce.pszUID.a = jid;
+ gce.bIsMe = (jid == m_szJid);
+
+ if (jid == szOwner)
+ gce.pszStatus.a = "Owner";
+ else if (!mir_strcmp(role, "superadmin"))
+ gce.pszStatus.a = "SuperAdmin";
+ else if (!mir_strcmp(role, "adminadd"))
+ gce.pszStatus.a = "Admin";
+ else
+ gce.pszStatus.a = "Participant";
+
+ if (gce.bIsMe)
+ szNick = ptrA(getUStringA(DBKEY_NICK));
+ else if (auto *pUser = FindUser(jid))
+ szNick = T2Utf(Clist_GetContactDisplayName(pUser->hContact)).get();
+ else
+ szNick = WAJid(jid).user;
+
+ gce.pszNick.a = szNick;
+ Chat_Event(&gce);
}
-
- gce.pszNick.w = wszNick;
- Chat_Event(&gce);
}
- CMStringW wszSubject(root["subject"].as_mstring());
- if (!wszSubject.IsEmpty()) {
- time_t iSubjectTime(root["subjectTime"].as_int());
- CMStringW wszSubjectSet(root["subjectOwner"].as_mstring());
+ if (auto *pszSubject = pGroup->getAttr("subject")) {
+ time_t iSubjectTime = pGroup->getAttrInt("s_t");
+ auto *pszUser = pGroup->getAttr("s_o");
+ if (m_szJid == pszUser)
+ szNick = ptrA(getUStringA(DBKEY_NICK));
+ else if (auto *pUser = FindUser(pszUser))
+ szNick = T2Utf(Clist_GetContactDisplayName(pUser->hContact)).get();
+ else
+ szNick = WAJid(pszUser).user;
GCEVENT gce = { m_szModuleName, 0, GC_EVENT_TOPIC };
- gce.pszID.w = pChatUser->si->ptszID;
- gce.pszUID.w = wszSubjectSet;
- gce.pszText.w = wszSubject;
+ gce.dwFlags = GCEF_UTF8;
+ gce.pszID.a = pChatUser->szId;
+ gce.pszUID.a = pszUser;
+ gce.pszText.a = pszSubject;
gce.time = iSubjectTime;
Chat_Event(&gce);
+
+ setUString(pChatUser->hContact, "Nick", pszSubject);
}
+
+ pChatUser->bInited = true;
+ CMStringW wszId(Utf2T(pChatUser->szId));
+ Chat_Control(m_szModuleName, wszId, m_bHideGroupchats ? WINDOW_HIDDEN : SESSION_INITDONE);
+ Chat_Control(m_szModuleName, wszId, SESSION_ONLINE);
}
diff --git a/protocols/WhatsApp/src/message.cpp b/protocols/WhatsApp/src/message.cpp
index b653b18688..4b002a3c64 100644
--- a/protocols/WhatsApp/src/message.cpp
+++ b/protocols/WhatsApp/src/message.cpp
@@ -188,7 +188,6 @@ void WhatsAppProto::ProcessMessage(WAMSG type, const Wa__WebMessageInfo &msg)
{
auto *key = msg.key;
auto *body = getBody(msg.message);
- bool bFromMe = key->fromme;
debugLogA("Got a message: %s", protobuf_c_text_to_string(&msg).c_str());
@@ -197,15 +196,9 @@ void WhatsAppProto::ProcessMessage(WAMSG type, const Wa__WebMessageInfo &msg)
auto *chatId = key->remotejid;
auto *msgId = key->id;
- WAUser *pUser = FindUser(chatId);
- if (pUser == nullptr) {
- if (type.bPrivateChat)
- pUser = AddUser(chatId, false, false);
- else if (type.bGroupChat)
- pUser = AddUser(chatId, false, true);
- }
+ WAUser *pUser = AddUser(chatId, false);
- if (!bFromMe && msg.pushname && pUser && !pUser->bIsGroupChat)
+ if (!key->fromme && msg.pushname && pUser && !pUser->bIsGroupChat)
setUString(pUser->hContact, "Nick", msg.pushname);
// try to extract some text
@@ -218,7 +211,7 @@ void WhatsAppProto::ProcessMessage(WAMSG type, const Wa__WebMessageInfo &msg)
pre.szMsgId = msgId;
if (type.bOffline)
pre.flags |= PREF_CREATEREAD;
- if (bFromMe)
+ if (key->fromme)
pre.flags |= PREF_SENT;
ProtoChainRecvMsg(pUser->hContact, &pre);
}
diff --git a/protocols/WhatsApp/src/proto.h b/protocols/WhatsApp/src/proto.h
index 8a8e3461a4..4f2fee4609 100644
--- a/protocols/WhatsApp/src/proto.h
+++ b/protocols/WhatsApp/src/proto.h
@@ -284,11 +284,12 @@ class WhatsAppProto : public PROTO<WhatsAppProto>
OBJLIST<WADevice> m_arDevices;
WAUser* FindUser(const char *szId);
- WAUser* AddUser(const char *szId, bool bTemporary, bool isChat = false);
+ WAUser* AddUser(const char *szId, bool bTemporary);
// Group chats /////////////////////////////////////////////////////////////////////////
- void InitChat(WAUser *pUser);
+ void GC_Init(WAUser *pUser);
+ void GC_GetMetadata(const char *szJid);
// UI //////////////////////////////////////////////////////////////////////////////////
@@ -353,6 +354,7 @@ class WhatsAppProto : public PROTO<WhatsAppProto>
void OnIqBlockList(const WANode &node);
void OnIqCountPrekeys(const WANode &node);
void OnIqDoNothing(const WANode &node);
+ void OnIqGcMetadata(const WANode &node);
void OnIqGetAvatar(const WANode &node);
void OnIqGetUsync(const WANode &node);
void OnIqPairDevice(const WANode &node);
diff --git a/protocols/WhatsApp/src/server.cpp b/protocols/WhatsApp/src/server.cpp
index 26a8015445..5dfbd34270 100644
--- a/protocols/WhatsApp/src/server.cpp
+++ b/protocols/WhatsApp/src/server.cpp
@@ -310,6 +310,10 @@ void WhatsAppProto::OnLoggedIn()
WSSendNode(
WANodeIq(IQ::GET, "privacy") << XCHILD("privacy"),
&WhatsAppProto::OnIqDoNothing);
+
+ for (auto &it : m_arUsers)
+ if (it->bIsGroupChat)
+ GC_Init(it);
}
void WhatsAppProto::OnLoggedOut(void)
diff --git a/protocols/WhatsApp/src/utils.cpp b/protocols/WhatsApp/src/utils.cpp
index 880b0e9469..a28deda31d 100644
--- a/protocols/WhatsApp/src/utils.cpp
+++ b/protocols/WhatsApp/src/utils.cpp
@@ -105,7 +105,7 @@ WAUser* WhatsAppProto::FindUser(const char *szId)
return m_arUsers.find(tmp);
}
-WAUser* WhatsAppProto::AddUser(const char *szId, bool bTemporary, bool isChat)
+WAUser* WhatsAppProto::AddUser(const char *szId, bool bTemporary)
{
auto *pUser = FindUser(szId);
if (pUser != nullptr)
@@ -114,9 +114,14 @@ WAUser* WhatsAppProto::AddUser(const char *szId, bool bTemporary, bool isChat)
MCONTACT hContact = db_add_contact();
Proto_AddToContact(hContact, m_szModuleName);
- if (isChat) {
+ pUser = new WAUser(hContact, mir_strdup(szId));
+ pUser->bIsGroupChat = WAJid(szId).isGroup();
+
+ if (pUser->bIsGroupChat) {
setByte(hContact, "ChatRoom", 1);
setString(hContact, "ChatRoomID", szId);
+
+ GC_Init(pUser);
}
else {
setString(hContact, DBKEY_ID, szId);
@@ -127,9 +132,6 @@ WAUser* WhatsAppProto::AddUser(const char *szId, bool bTemporary, bool isChat)
if (bTemporary)
Contact::RemoveFromList(hContact);
- pUser = new WAUser(hContact, mir_strdup(szId));
- pUser->bIsGroupChat = isChat;
-
mir_cslock lck(m_csUsers);
m_arUsers.insert(pUser);
return pUser;