diff options
author | ElzorFox <elzorfox@ya.ru> | 2020-06-16 16:22:22 +0500 |
---|---|---|
committer | ElzorFox <elzorfox@ya.ru> | 2020-06-16 16:22:22 +0500 |
commit | ad727a136a6b592b14cfaa719ae895c119391044 (patch) | |
tree | bfa3fe295d40b75e1cde79a51404bd4987d06cc5 /protocols/VKontakte | |
parent | 436e303e24e5046d6cc52ac3da51a0b51adbef36 (diff) |
VKontakte: prepare for upgrade VK API version - part 3
Diffstat (limited to 'protocols/VKontakte')
-rw-r--r-- | protocols/VKontakte/src/misc.cpp | 11 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk.h | 2 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_chats.cpp | 282 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_history.cpp | 10 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_messages.cpp | 152 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_pollserver.cpp | 2 | ||||
-rw-r--r-- | protocols/VKontakte/src/vk_proto.h | 1 | ||||
-rw-r--r-- | protocols/VKontakte/src/vkjs.js | 55 |
8 files changed, 497 insertions, 18 deletions
diff --git a/protocols/VKontakte/src/misc.cpp b/protocols/VKontakte/src/misc.cpp index 82cf1fb737..c3ff2f4f8e 100644 --- a/protocols/VKontakte/src/misc.cpp +++ b/protocols/VKontakte/src/misc.cpp @@ -1312,7 +1312,12 @@ CMStringW CVkProto::GetFwdMessages(const JSONNode &jnMessages, const JSONNode &j for (auto &jnUser : jnFUsers) {
int iUserId = jnUser["id"].as_int();
- CMStringW wszNick(FORMAT, L"%s %s", jnUser["first_name"].as_mstring().c_str(), jnUser["last_name"].as_mstring().c_str());
+ CMStringW wszNick(jnUser["name"].as_mstring());
+
+ if (!wszNick.IsEmpty())
+ iUserId *= -1;
+ else
+ wszNick.AppendFormat(L"%s %s", jnUser["first_name"].as_mstring().c_str(), jnUser["last_name"].as_mstring().c_str());
CVkUserInfo *vkUser = new CVkUserInfo(jnUser["id"].as_int(), false, wszNick, UserProfileUrl(iUserId), FindUser(iUserId));
vkUsers.insert(vkUser);
@@ -1320,7 +1325,11 @@ CMStringW CVkProto::GetFwdMessages(const JSONNode &jnMessages, const JSONNode &j for (auto &jnMsg : jnMessages) {
+#if (VK_NEW_API == 1)
+ UINT uid = jnMsg["from_id"].as_int();
+#else
UINT uid = jnMsg["user_id"].as_int();
+#endif
CVkUserInfo *vkUser = vkUsers.find((CVkUserInfo *)&uid);
CMStringW wszNick, wszUrl;
diff --git a/protocols/VKontakte/src/vk.h b/protocols/VKontakte/src/vk.h index 06eb52bf97..2ab0052a98 100644 --- a/protocols/VKontakte/src/vk.h +++ b/protocols/VKontakte/src/vk.h @@ -88,6 +88,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #define VK_USER_DEACTIVATE_ACTION 9321
+#define VK_CHAT_FLAG 2000000000
+
#define VK_NEW_API 0
#if (VK_NEW_API == 0)
diff --git a/protocols/VKontakte/src/vk_chats.cpp b/protocols/VKontakte/src/vk_chats.cpp index cf385b0644..9106e4a6b3 100644 --- a/protocols/VKontakte/src/vk_chats.cpp +++ b/protocols/VKontakte/src/vk_chats.cpp @@ -36,20 +36,16 @@ CVkChatInfo* CVkProto::AppendConversationChat(int iChatId, const JSONNode& jnIte return nullptr;
- if (!jnItem)
- return nullptr;
-
-
- const JSONNode& jnLastMessage = jnItem["last_message"];
- const JSONNode& jnChatSettings = jnItem["chat_settings"];
+ const JSONNode& jnConversation = jnItem ? jnItem["conversation"] : nullNode;
+ const JSONNode& jnLastMessage = jnItem ? jnItem["last_message"] : nullNode;
+ const JSONNode& jnChatSettings = jnConversation ? jnConversation["chat_settings"] : nullNode;
if (jnLastMessage) {
const JSONNode& jnAction = jnLastMessage["action"];
if (jnAction) {
CMStringW wszActionType(jnAction["type"].as_mstring());
- if ((wszActionType == L"chat_kick_user") && (jnAction["member_id"].as_int() == m_myUserId)) {
+ if ((wszActionType == L"chat_kick_user") && (jnAction["member_id"].as_int() == m_myUserId))
return nullptr;
- }
}
}
@@ -58,7 +54,6 @@ CVkChatInfo* CVkProto::AppendConversationChat(int iChatId, const JSONNode& jnIte return nullptr;
-
CVkChatInfo* vkChatInfo = m_chats.find((CVkChatInfo*)&iChatId);
if (vkChatInfo != nullptr)
return vkChatInfo;
@@ -96,7 +91,7 @@ CVkChatInfo* CVkProto::AppendConversationChat(int iChatId, const JSONNode& jnIte db_unset(si->hContact, m_szModuleName, "off");
- if (wszState != L"in") {
+ if (jnChatSettings && wszState != L"in") {
setByte(si->hContact, "off", 1);
m_chats.remove(vkChatInfo);
return nullptr;
@@ -184,7 +179,7 @@ void CVkProto::RetrieveChatInfo(CVkChatInfo *cc) Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.RetrieveChatInfo", true, &CVkProto::OnReceiveChatInfo)
<< INT_PARAM("chatid", cc->m_iChatId)
- << INT_PARAM("func_v", cc->m_bHistoryRead ? 1 : 2)
+ << INT_PARAM("func_v", cc->m_bHistoryRead ? 1 : 2 + VK_NEW_API)
)->pUserInfo = cc;
}
@@ -203,6 +198,7 @@ void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe if (m_chats.indexOf(cc) == -1)
return;
+#if (VK_NEW_API==1)
const JSONNode &jnInfo = jnResponse["info"];
if (jnInfo) {
if (jnInfo["title"])
@@ -216,7 +212,12 @@ void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe cc->m_iAdminId = jnInfo["admin_id"].as_int();
}
- const JSONNode &jnUsers = jnResponse["users"];
+
+ if (!jnResponse["users"])
+ return;
+
+ const JSONNode &jnUsers = jnResponse["users"]["profiles"];
+
if (jnUsers) {
for (auto &it : cc->m_users)
it->m_bDel = true;
@@ -302,6 +303,7 @@ void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe const JSONNode &jnMsgs = jnResponse["msgs"];
const JSONNode &jnFUsers = jnResponse["fwd_users"];
+ const JSONNode &jnGUsers = jnResponse["groups"];
if (jnMsgs) {
const JSONNode &jnItems = jnMsgs["items"];
if (jnItems) {
@@ -309,7 +311,7 @@ void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe if (!jnMsg)
break;
- AppendChatMessage(cc->m_iChatId, jnMsg, jnFUsers, true);
+ AppendChatConversationMessage(cc->m_iChatId, jnMsg, jnFUsers, true);
}
cc->m_bHistoryRead = true;
}
@@ -319,6 +321,125 @@ void CVkProto::OnReceiveChatInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe AppendChatMessage(cc, p->m_uid, p->m_date, p->m_wszBody, p->m_bHistory, p->m_bIsAction);
cc->m_msgs.destroy();
+#else
+ const JSONNode& jnInfo = jnResponse["info"];
+ if (jnInfo) {
+ if (jnInfo["title"])
+ SetChatTitle(cc, jnInfo["title"].as_mstring());
+
+ if (jnInfo["left"].as_bool() || jnInfo["kicked"].as_bool()) {
+ setByte(cc->m_hContact, "kicked", jnInfo["kicked"].as_bool());
+ LeaveChat(cc->m_iChatId);
+ return;
+ }
+ cc->m_iAdminId = jnInfo["admin_id"].as_int();
+ }
+
+ const JSONNode& jnUsers = jnResponse["users"];
+ if (jnUsers) {
+ for (auto& it : cc->m_users)
+ it->m_bDel = true;
+
+ for (auto& jnUser : jnUsers) {
+ if (!jnUser)
+ break;
+
+ LONG uid = jnUser["id"].as_int();
+ bool bIsGroup = jnUser["type"].as_mstring() == L"group";
+ if (bIsGroup)
+ uid *= -1;
+
+ wchar_t wszId[20];
+ _itow(uid, wszId, 10);
+
+ bool bNew;
+ CVkChatUser* cu = cc->m_users.find((CVkChatUser*)&uid);
+ if (cu == nullptr) {
+ cc->m_users.insert(cu = new CVkChatUser(uid));
+ bNew = true;
+ }
+ else
+ bNew = cu->m_bUnknown;
+ cu->m_bDel = false;
+
+ CMStringW wszNick(ptrW(db_get_wsa(cc->m_hContact, m_szModuleName, CMStringA(FORMAT, "nick%d", cu->m_uid))));
+ if (wszNick.IsEmpty())
+ wszNick = bIsGroup ?
+ jnUser["name"].as_mstring() :
+ jnUser["first_name"].as_mstring().Trim() + L" " + jnUser["last_name"].as_mstring().Trim();
+
+
+ cu->m_wszNick = mir_wstrdup(wszNick);
+ cu->m_bUnknown = false;
+
+ if (bNew) {
+ GCEVENT gce = { m_szModuleName, 0, GC_EVENT_JOIN };
+ gce.pszID.w = cc->m_wszId;
+ gce.bIsMe = uid == m_myUserId;
+ gce.pszUID.w = wszId;
+ gce.pszNick.w = wszNick;
+ gce.pszStatus.w = TranslateW(sttStatuses[uid == cc->m_iAdminId]);
+ gce.dwItemData = (INT_PTR)cu;
+ Chat_Event(&gce);
+ }
+ }
+
+ for (auto& cu : cc->m_users.rev_iter()) {
+ if (!cu->m_bDel)
+ continue;
+
+ wchar_t wszId[20];
+ _itow(cu->m_uid, wszId, 10);
+ CMStringW wszNick(FORMAT, L"%s (%s)", cu->m_wszNick.get(), UserProfileUrl(cu->m_uid).c_str());
+
+ GCEVENT gce = { m_szModuleName, 0, GC_EVENT_PART };
+ gce.pszID.w = cc->m_wszId;
+ gce.pszUID.w = wszId;
+ gce.dwFlags = GCEF_NOTNOTIFY;
+ gce.time = time(0);
+ gce.pszNick.w = wszNick;
+ Chat_Event(&gce);
+
+ cc->m_users.removeItem(&cu);
+ }
+ }
+
+ const JSONNode& jnMsgsUsers = jnResponse["msgs_users"];
+ for (auto& jnUser : jnMsgsUsers) {
+ LONG uid = jnUser["id"].as_int();
+ CVkChatUser* cu = cc->m_users.find((CVkChatUser*)&uid);
+ if (cu)
+ continue;
+
+ MCONTACT hContact = FindUser(uid);
+ if (hContact)
+ continue;
+
+ hContact = SetContactInfo(jnUser, true, VKContactType::vkContactMUCUser);
+
+ }
+
+ const JSONNode& jnMsgs = jnResponse["msgs"];
+ const JSONNode& jnFUsers = jnResponse["fwd_users"];
+ if (jnMsgs) {
+ const JSONNode& jnItems = jnMsgs["items"];
+ if (jnItems) {
+ for (auto& jnMsg : jnItems) {
+ if (!jnMsg)
+ break;
+
+ AppendChatMessage(cc->m_iChatId, jnMsg, jnFUsers, true);
+ }
+ cc->m_bHistoryRead = true;
+ }
+ }
+
+ for (auto& p : cc->m_msgs)
+ AppendChatMessage(cc, p->m_uid, p->m_date, p->m_wszBody, p->m_bHistory, p->m_bIsAction);
+
+ cc->m_msgs.destroy();
+#endif
+
}
void CVkProto::SetChatTitle(CVkChatInfo *cc, LPCWSTR wszTopic)
@@ -338,6 +459,141 @@ void CVkProto::SetChatTitle(CVkChatInfo *cc, LPCWSTR wszTopic) /////////////////////////////////////////////////////////////////////////////////////////
+void CVkProto::AppendChatConversationMessage(int id, const JSONNode& jnMsg, const JSONNode& jnFUsers, bool bIsHistory)
+{
+ debugLogA("CVkProto::AppendChatMessage");
+ CVkChatInfo* cc = AppendConversationChat(id, nullNode);
+ if (cc == nullptr)
+ return;
+
+ int mid = jnMsg["id"].as_int();
+ int uid = jnMsg["from_id"].as_int();
+ bool bIsAction = false;
+
+ int msgTime = jnMsg["date"].as_int();
+ time_t now = time(0);
+ if (!msgTime || msgTime > now)
+ msgTime = now;
+
+ CMStringW wszBody(jnMsg["text"].as_mstring());
+
+ const JSONNode& jnFwdMessages = jnMsg["fwd_messages"];
+ if (jnFwdMessages && !jnFwdMessages.empty()) {
+ CMStringW wszFwdMessages = GetFwdMessages(jnFwdMessages, jnFUsers, bbcNo);
+ if (!wszBody.IsEmpty())
+ wszFwdMessages = L"\n" + wszFwdMessages;
+ wszBody += wszFwdMessages;
+ }
+
+ const JSONNode& jnAttachments = jnMsg["attachments"];
+ if (jnAttachments && !jnAttachments.empty()) {
+ CMStringW wszAttachmentDescr = GetAttachmentDescr(jnAttachments, bbcNo);
+
+ if (wszAttachmentDescr == L"== FilterAudioMessages ==")
+ return;
+
+ if (!wszBody.IsEmpty())
+ wszAttachmentDescr = L"\n" + wszAttachmentDescr;
+ wszBody += wszAttachmentDescr;
+ }
+
+ if (m_vkOptions.bAddMessageLinkToMesWAtt && ((jnAttachments && !jnAttachments.empty())||(jnFwdMessages && !jnFwdMessages.empty())))
+ wszBody += SetBBCString(TranslateT("Message link"), bbcNo, vkbbcUrl,
+ CMStringW(FORMAT, L"https://vk.com/im?sel=c%d&msgid=%d", cc->m_iChatId, mid));
+
+ if (jnMsg["action"] && jnMsg["action"]["type"]) {
+ bIsAction = true;
+ CMStringW wszAction = jnMsg["action"]["type"].as_mstring();
+
+ if (wszAction == L"chat_create") {
+ CMStringW wszActionText = jnMsg["action"]["text"].as_mstring();
+ wszBody.AppendFormat(L"%s \"%s\"", TranslateT("create chat"), wszActionText.IsEmpty() ? L" " : wszActionText.c_str());
+ }
+ else if (wszAction == L"chat_kick_user") {
+ CMStringW wszActionMid = jnMsg["action"]["member_id"].as_mstring();
+ if (wszActionMid.IsEmpty())
+ wszBody = TranslateT("kick user");
+ else {
+ CMStringW wszUid(FORMAT, L"%d", uid);
+ if (wszUid == wszActionMid) {
+ if (cc->m_bHistoryRead)
+ return;
+ wszBody.AppendFormat(L" (%s) %s", UserProfileUrl(uid).c_str(), TranslateT("left chat"));
+ }
+ else {
+ int a_uid = 0;
+ int iReadCount = swscanf(wszActionMid, L"%d", &a_uid);
+ if (iReadCount == 1) {
+ CVkChatUser* cu = cc->m_users.find((CVkChatUser*)&a_uid);
+ if (cu == nullptr)
+ wszBody.AppendFormat(L"%s (%s)", TranslateT("kick user"), UserProfileUrl(a_uid).c_str());
+ else
+ wszBody.AppendFormat(L"%s %s (%s)", TranslateT("kick user"), cu->m_wszNick.get(), UserProfileUrl(a_uid).c_str());
+ }
+ else wszBody = TranslateT("kick user");
+ }
+ }
+ }
+ else if (wszAction == L"chat_invite_user" || wszAction == L"chat_invite_user_by_link") {
+ CMStringW wszActionMid = jnMsg["action"]["member_id"].as_mstring();
+ if (wszActionMid.IsEmpty())
+ wszBody = TranslateT("invite user");
+ else {
+ CMStringW wszUid(FORMAT, L"%d", uid);
+ if (wszUid == wszActionMid)
+ wszBody.AppendFormat(L" (%s) %s", UserProfileUrl(uid).c_str(), TranslateT("returned to chat"));
+ else {
+ int a_uid = 0;
+ int iReadCount = swscanf(wszActionMid, L"%d", &a_uid);
+ if (iReadCount == 1) {
+ CVkChatUser* cu = cc->m_users.find((CVkChatUser*)&a_uid);
+ if (cu == nullptr)
+ wszBody.AppendFormat(L"%s (%s)", TranslateT("invite user"), UserProfileUrl(a_uid).c_str());
+ else
+ wszBody.AppendFormat(L"%s %s (%s)", TranslateT("invite user"), cu->m_wszNick.get(), UserProfileUrl(a_uid).c_str());
+ }
+ else wszBody = TranslateT("invite user");
+ }
+ }
+ }
+ else if (wszAction == L"chat_title_update") {
+ CMStringW wszTitle = jnMsg["action"]["text"].as_mstring();
+ wszBody.AppendFormat(L"%s \"%s\"", TranslateT("change chat title to"), wszTitle.IsEmpty() ? L" " : wszTitle.c_str());
+
+ if (!bIsHistory)
+ SetChatTitle(cc, wszTitle);
+ }
+ else if (wszAction == L"chat_pin_message")
+ wszBody = TranslateT("pin message");
+ else if (wszAction == L"chat_unpin_message")
+ wszBody = TranslateT("unpin message");
+ else if (wszAction == L"chat_photo_update")
+ wszBody.Replace(TranslateT("Attachments:"), TranslateT("changed chat cover:"));
+ else if (wszAction == L"chat_photo_remove")
+ wszBody = TranslateT("deleted chat cover");
+ else
+ wszBody.AppendFormat(L": %s (%s)", TranslateT("chat action not supported"), wszAction.c_str());
+ }
+
+ wszBody.Replace(L"%", L"%%");
+
+ if (cc->m_bHistoryRead) {
+ AppendChatMessage(cc, uid, msgTime, wszBody, bIsHistory, bIsAction);
+ }
+ else {
+ CVkChatMessage* cm = cc->m_msgs.find((CVkChatMessage*)&mid);
+ if (cm == nullptr)
+ cc->m_msgs.insert(cm = new CVkChatMessage(mid));
+
+ cm->m_uid = uid;
+ cm->m_date = msgTime;
+ cm->m_wszBody = mir_wstrdup(wszBody);
+ cm->m_bHistory = bIsHistory;
+ cm->m_bIsAction = bIsAction;
+ }
+}
+
+
void CVkProto::AppendChatMessage(int id, const JSONNode &jnMsg, const JSONNode &jnFUsers, bool bIsHistory)
{
debugLogA("CVkProto::AppendChatMessage");
diff --git a/protocols/VKontakte/src/vk_history.cpp b/protocols/VKontakte/src/vk_history.cpp index 7695e33859..0fdf83b477 100644 --- a/protocols/VKontakte/src/vk_history.cpp +++ b/protocols/VKontakte/src/vk_history.cpp @@ -248,14 +248,20 @@ void CVkProto::OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpReque #if (VK_NEW_API == 1)
CMStringW wszBody(jnMsg["text"].as_mstring());
int uid = jnMsg["peer_id"].as_int();
+
+ int iReadMsg = getDword(param->hContact, "in_read", 0);
+ int isRead = (uid <= iReadMsg);
+
+
#else
CMStringW wszBody(jnMsg["body"].as_mstring());
int uid = jnMsg["user_id"].as_int();
+ int isRead = jnMsg["read_state"].as_int();
#endif
int datetime = jnMsg["date"].as_int();
int isOut = jnMsg["out"].as_int();
- int isRead = jnMsg["read_state"].as_int();
+
const JSONNode &jnFwdMessages = jnMsg["fwd_messages"];
if (jnFwdMessages && !jnFwdMessages.empty()) {
@@ -279,7 +285,7 @@ void CVkProto::OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpReque wszBody += wszAttachmentDescr;
}
- if (m_vkOptions.bAddMessageLinkToMesWAtt && (jnAttachments || jnFwdMessages))
+ if (m_vkOptions.bAddMessageLinkToMesWAtt && ((jnAttachments && !jnAttachments.empty()) || (jnFwdMessages && !jnFwdMessages.empty())))
wszBody += SetBBCString(TranslateT("Message link"), m_vkOptions.BBCForAttachments(), vkbbcUrl,
CMStringW(FORMAT, L"https://vk.com/im?sel=%d&msgid=%d", uid, mid));
diff --git a/protocols/VKontakte/src/vk_messages.cpp b/protocols/VKontakte/src/vk_messages.cpp index bb020a3594..167be76ee7 100644 --- a/protocols/VKontakte/src/vk_messages.cpp +++ b/protocols/VKontakte/src/vk_messages.cpp @@ -187,10 +187,15 @@ void CVkProto::RetrieveMessagesByIds(const CMStringA &mids) debugLogA("CVkProto::RetrieveMessagesByIds");
if (!IsOnline() || mids.IsEmpty())
return;
-
+#if (VK_NEW_API == 1)
+ Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.RetrieveMessagesConversationByIds", true, &CVkProto::OnReceiveMessages, AsyncHttpRequest::rpHigh)
+ << CHAR_PARAM("mids", mids)
+ );
+#else
Push(new AsyncHttpRequest(this, REQUEST_GET, "/method/execute.RetrieveMessagesByIds", true, &CVkProto::OnReceiveMessages, AsyncHttpRequest::rpHigh)
<< CHAR_PARAM("mids", mids)
);
+#endif
}
void CVkProto::RetrieveUnreadMessages()
@@ -226,12 +231,153 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe debugLogA("CVkProto::OnReceiveMessages numMessages = %d", numMessages);
+#if (VK_NEW_API == 1)
+ for (auto& jnMsg : jnMsgs) {
+ if (!jnMsg) {
+ debugLogA("CVkProto::OnReceiveMessages pMsg == nullptr");
+ break;
+ }
+
+
+ UINT mid = jnMsg["id"].as_int();
+ CMStringW wszBody(jnMsg["text"].as_mstring());
+ UINT datetime = jnMsg["date"].as_int();
+ int isOut = jnMsg["out"].as_int();
+ int isRead = jnMsg["read_state"].as_int();
+ int uid = jnMsg["peer_id"].as_int();
+
+ MCONTACT hContact = 0;
+
+ int chat_id = uid / VK_CHAT_FLAG ? uid % VK_CHAT_FLAG : 0;
+ if (chat_id == 0)
+ hContact = FindUser(uid, true);
+
+ char szMid[40];
+ _itoa(mid, szMid, 10);
+ if (m_vkOptions.iMarkMessageReadOn == MarkMsgReadOn::markOnReceive || chat_id != 0) {
+ if (!mids.IsEmpty())
+ mids.AppendChar(',');
+ mids.Append(szMid);
+ }
+
+ bool bUseServerReadFlag = m_vkOptions.bSyncReadMessageStatusFromServer ? true : !m_vkOptions.bMesAsUnread;
+
+ if (chat_id != 0) {
+ debugLogA("CVkProto::OnReceiveMessages chat_id != 0");
+ CMStringW action_chat = jnMsg["action"]["type"].as_mstring();
+ int action_mid = _wtoi(jnMsg["action"]["member_id"].as_mstring());
+ if ((action_chat == L"chat_kick_user") && (action_mid == m_myUserId))
+ KickFromChat(chat_id, uid, jnMsg, jnFUsers);
+ else {
+ MCONTACT chatContact = FindChat(chat_id);
+ if (chatContact && getBool(chatContact, "kicked", true))
+ db_unset(chatContact, m_szModuleName, "kicked");
+ AppendChatConversationMessage(chat_id, jnMsg, jnFUsers, false);
+ }
+ continue;
+ }
+
+ const JSONNode& jnFwdMessages = jnMsg["fwd_messages"];
+ if (jnFwdMessages && !jnFwdMessages.empty()) {
+ CMStringW wszFwdMessages = GetFwdMessages(jnFwdMessages, jnFUsers, m_vkOptions.BBCForAttachments());
+ if (!wszBody.IsEmpty())
+ wszFwdMessages = L"\n" + wszFwdMessages;
+ wszBody += wszFwdMessages;
+ }
+
+ CMStringW wszBodyNoAttachments = wszBody;
+
+
+ CMStringW wszAttachmentDescr;
+ const JSONNode& jnAttachments = jnMsg["attachments"];
+ if (jnAttachments && !jnAttachments.empty()) {
+ wszAttachmentDescr = GetAttachmentDescr(jnAttachments, m_vkOptions.BBCForAttachments());
+
+ if (wszAttachmentDescr == L"== FilterAudioMessages ==") {
+ if (hContact && (mid > getDword(hContact, "lastmsgid", -1)))
+ setDword(hContact, "lastmsgid", mid);
+ continue;
+ }
+
+ if (!wszBody.IsEmpty())
+ wszBody += L"\n";
+ wszBody += wszAttachmentDescr;
+ }
+
+ if (m_vkOptions.bAddMessageLinkToMesWAtt && ((jnAttachments && !jnAttachments.empty()) || (jnFwdMessages && !jnFwdMessages.empty())))
+ wszBody += SetBBCString(TranslateT("Message link"), m_vkOptions.BBCForAttachments(), vkbbcUrl,
+ CMStringW(FORMAT, L"https://vk.com/im?sel=%d&msgid=%d", uid, mid));
+
+ time_t update_time = (time_t)jnMsg["update_time"].as_int();
+ bool bEdited = (update_time != 0);
+
+ if (bEdited) {
+ wchar_t ttime[64];
+ _locale_t locale = _create_locale(LC_ALL, "");
+ _wcsftime_l(ttime, _countof(ttime), TranslateT("%x at %X"), localtime(&update_time), locale);
+ _free_locale(locale);
+
+ wszBody = SetBBCString(
+ CMStringW(FORMAT, TranslateT("Edited message (updated %s):\n"), ttime),
+ m_vkOptions.BBCForAttachments(), vkbbcB) +
+ wszBody;
+
+ CMStringW wszOldMsg;
+ if (GetMessageFromDb(mid, datetime, wszOldMsg))
+ wszBody += SetBBCString(TranslateT("\nOriginal message:\n"), m_vkOptions.BBCForAttachments(), vkbbcB) +
+ wszOldMsg;
+ }
+
+ PROTORECVEVENT recv = {};
+
+ if (isRead && bUseServerReadFlag)
+ recv.flags |= PREF_CREATEREAD;
+
+ if (isOut)
+ recv.flags |= PREF_SENT;
+ else if (m_vkOptions.bUserForceInvisibleOnActivity && time(0) - datetime < 60 * m_vkOptions.iInvisibleInterval)
+ SetInvisible(hContact);
+
+ T2Utf pszBody(wszBody);
+ recv.timestamp = bEdited ? datetime : (m_vkOptions.bUseLocalTime ? time(0) : datetime);
+ recv.szMessage = pszBody;
+
+ debugLogA("CVkProto::OnReceiveMessages mid = %d, datetime = %d, isOut = %d, isRead = %d, uid = %d, Edited = %d", mid, datetime, isOut, isRead, uid, (int)bEdited);
+
+ if (!IsMessageExist(mid, vkALL) || bEdited) {
+ debugLogA("CVkProto::OnReceiveMessages new or edited message");
+ recv.szMsgId = szMid;
+ ProtoChainRecvMsg(hContact, &recv);
+ if (mid > getDword(hContact, "lastmsgid", -1))
+ setDword(hContact, "lastmsgid", mid);
+ }
+ else if (m_vkOptions.bLoadSentAttachments && !wszAttachmentDescr.IsEmpty()) {
+ CMStringW wszOldMsg;
+
+ if (GetMessageFromDb(mid, datetime, wszOldMsg) && (wszOldMsg == wszBody))
+ continue;
+
+ if (wszBodyNoAttachments != wszOldMsg)
+ continue;
+
+ debugLogA("CVkProto::OnReceiveMessages add attachments");
+
+ T2Utf pszAttach(wszAttachmentDescr);
+ recv.timestamp = isOut ? time(0) : datetime;
+ recv.szMessage = pszAttach;
+ recv.szMsgId = strcat(szMid, "_");
+ ProtoChainRecvMsg(hContact, &recv);
+ }
+ }
+
+#else
for (auto &jnMsg : jnMsgs) {
if (!jnMsg) {
debugLogA("CVkProto::OnReceiveMessages pMsg == nullptr");
break;
}
+
UINT mid = jnMsg["id"].as_int();
CMStringW wszBody(jnMsg["body"].as_mstring());
UINT datetime = jnMsg["date"].as_int();
@@ -361,6 +507,7 @@ void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pRe ProtoChainRecvMsg(hContact, &recv);
}
}
+#endif
if (!mids.IsEmpty())
MarkMessagesRead(mids);
@@ -450,6 +597,9 @@ void CVkProto::OnReceiveDlgs(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) if (IsGroupUser(hContact))
szGroupIds.AppendFormat(szGroupIds.IsEmpty() ? "%d" : ",%d", -1 * iUserId);
+ setDword(hContact, "in_read", jnConversation["in_read"].as_int());
+ setDword(hContact, "out_read", jnConversation["out_read"].as_int());
+
/*
if (g_bMessageState) {
bool bIsOut = jnLastMessage["out"].as_bool();
diff --git a/protocols/VKontakte/src/vk_pollserver.cpp b/protocols/VKontakte/src/vk_pollserver.cpp index aaee82e5fa..81ec8fc83b 100644 --- a/protocols/VKontakte/src/vk_pollserver.cpp +++ b/protocols/VKontakte/src/vk_pollserver.cpp @@ -58,7 +58,7 @@ void CVkProto::OnReceivePollingInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest * m_pollingTs ? m_pollingTs.get() : "<nullptr>",
m_pollingKey ? m_pollingKey.get() : "<nullptr>",
m_pollingServer ? m_pollingServer.get() : "<nullptr>");
-
+
if (m_pollingTs != nullptr && m_pollingKey != nullptr && m_pollingServer != nullptr) {
debugLogA("CVkProto::OnReceivePollingInfo PollingThread starting...");
m_hPollingThread = ForkThreadEx(&CVkProto::PollingThread, nullptr, nullptr);
diff --git a/protocols/VKontakte/src/vk_proto.h b/protocols/VKontakte/src/vk_proto.h index 11602452ca..ca60dfdf5d 100644 --- a/protocols/VKontakte/src/vk_proto.h +++ b/protocols/VKontakte/src/vk_proto.h @@ -391,6 +391,7 @@ private: CVkChatInfo* AppendConversationChat(int iChatId, const JSONNode& jnItem);
CVkChatInfo* AppendChat(int id, const JSONNode &jnNode);
void SetChatTitle(CVkChatInfo *cc, LPCWSTR wszTopic);
+ void AppendChatConversationMessage(int id, const JSONNode& jnMsg, const JSONNode& jnFUsers, bool bIsHistory);
void AppendChatMessage(int id, const JSONNode &jnMsg, const JSONNode &jnFUsers, bool bIsHistory);
void AppendChatMessage(CVkChatInfo *cc, LONG uid, int msgTime, LPCWSTR pwszBody, bool bIsHistory, bool bIsAction = false);
void RetrieveChatInfo(CVkChatInfo*);
diff --git a/protocols/VKontakte/src/vkjs.js b/protocols/VKontakte/src/vkjs.js index 8741b09024..603fd7f692 100644 --- a/protocols/VKontakte/src/vkjs.js +++ b/protocols/VKontakte/src/vkjs.js @@ -169,6 +169,27 @@ var FUsers = API.users.get({ "user_ids": Uids, "name_case": "gen" }); return { "Msgs": Msgs, "fwd_users": FUsers }; // Stored procedure name: RetrieveMessagesByIds = End +// Stored procedure name: RetrieveMessagesConversationByIds = Begin +// Arguments: +// Args.mids + +var Msgs = API.messages.getById({ "message_ids": Args.mids }); +var FMsgs = Msgs.items@.fwd_messages; +var Idx = 0; +var Uids = []; +while (Idx < FMsgs.length) { + var Jdx = 0; + var CFMsgs = parseInt(FMsgs[Idx].length); + while (Jdx < CFMsgs) { + Uids.unshift(FMsgs[Idx][Jdx].from_id); + Jdx = Jdx + 1; + }; + Idx = Idx + 1; +}; +var FUsers = API.users.get({ "user_ids": Uids, "name_case": "gen" }); +return { "Msgs": Msgs, "fwd_users": FUsers }; +// Stored procedure name: RetrieveMessagesConversationByIds = End + // Stored procedure name: RetrieveUnreadMessages = Begin // Arguments: no @@ -310,6 +331,40 @@ var FUsers = API.users.get({ "user_ids": Uids, "name_case": "gen" }); var MsgUsers = API.users.get({ "user_ids": ChatMsg.items@.user_id, "fields":"id,first_name,last_name"}); return { "info": Info, "users": ChatUsers, "msgs": ChatMsg, "fwd_users": FUsers, "msgs_users": MsgUsers }; + + +// ver 3 +var Info = API.messages.getChat({ "chat_id": Args.chatid }); +var ChatUsers = API.messages.getConversationMembers({ "peer_id": 2000000000 + parseInt(Args.chatid), "fields": "id,first_name,last_name" }); +var ChatMsg = API.messages.getHistory({ "chat_id": Args.chatid, "count": 20, "rev": 0 }); +var UR = parseInt(ChatMsg.unread); +if (UR > 20) { + if (UR > 200) + UR = 200; + ChatMsg = API.messages.getHistory({ "chat_id": Args.chatid, "count": UR, "rev": 0 }); +}; +var FMsgs = ChatMsg.items@.fwd_messages; +var Idx = 0; +var Uids = []; +var GUids =[]; +while (Idx < FMsgs.length) { + var Jdx = 0; + var CFMsgs = parseInt(FMsgs[Idx].length); + while (Jdx < CFMsgs) { + if (FMsgs[Idx][Jdx].from_id>0) { + Uids.unshift(FMsgs[Idx][Jdx].from_id); + } else { + GUids.unshift(-1*FMsgs[Idx][Jdx].from_id); + }; + Jdx = Jdx + 1; + }; + Idx = Idx + 1; +}; +var FUsers = API.users.get({ "user_ids": Uids, "name_case": "gen" }); +var GUsers = API.groups.getById({ "group_ids": GUids }); +var MsgUsers = API.users.get({ "user_ids": ChatMsg.items@.from_id, "fields":"id,first_name,last_name"}); + +return { "info": Info, "users": ChatUsers, "msgs": ChatMsg, "fwd_users": FUsers + GUsers, "msgs_users": MsgUsers}; // Stored procedure name: RetrieveChatInfo = End // Stored procedure name: DestroyKickChat = Begin |