void CVkProto::AppendChatMessage(int id, JSONNODE *pMsg, bool bIsHistory) { CVkChatInfo *cc = AppendChat(id, NULL); if (cc == NULL) return; int mid = json_as_int(json_get(pMsg, "mid")); int isOut = json_as_int(json_get(pMsg, "out")); int uid = json_as_int(json_get(pMsg, "uid")); int msgTime = json_as_int(json_get(pMsg, "date")); time_t now = time(NULL); if (!msgTime || msgTime > now) msgTime = now; ptrT tszBody(json_as_string(json_get(pMsg, "body"))); JSONNODE *pAttachments = json_get(pMsg, "attachments"); if (pAttachments != NULL) tszBody = mir_tstrdup(CMString(tszBody) + GetAttachmentDescr(pAttachments)); if (cc->m_bHistoryRead) AppendChatMessage(cc, mid, uid, msgTime, tszBody, bIsHistory); else { CVkChatMessage *cm = cc->m_msgs.find((CVkChatMessage *)&mid); if (cm == NULL) cc->m_msgs.insert(cm = new CVkChatMessage(mid)); cm->m_uid = uid; cm->m_date = msgTime; cm->m_tszBody = tszBody.detouch(); cm->m_bHistory = bIsHistory; } }
void CVkProto::OnReceiveMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveMessages %d", reply->resultCode); if (reply->resultCode != 200) return; JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse) return; if (!jnResponse["Msgs"]) return; CMStringA mids; int numMessages = jnResponse["Msgs"]["count"].as_int(); const JSONNode &jnMsgs = jnResponse["Msgs"]["items"]; const JSONNode &jnFUsers = jnResponse["fwd_users"]; debugLogA("CVkProto::OnReceiveMessages numMessages = %d", numMessages); for (auto it = jnMsgs.begin(); it != jnMsgs.end(); ++it) { const JSONNode &jnMsg = (*it); if (!jnMsg) { debugLogA("CVkProto::OnReceiveMessages pMsg == NULL"); break; } UINT mid = jnMsg["id"].as_int(); CMString tszBody(jnMsg["body"].as_mstring()); int datetime = jnMsg["date"].as_int(); int isOut = jnMsg["out"].as_int(); int isRead = jnMsg["read_state"].as_int(); int uid = jnMsg["user_id"].as_int(); const JSONNode &jnFwdMessages = jnMsg["fwd_messages"]; if (jnFwdMessages) { CMString tszFwdMessages = GetFwdMessages(jnFwdMessages, jnFUsers, m_vkOptions.BBCForAttachments()); if (!tszBody.IsEmpty()) tszFwdMessages = _T("\n") + tszFwdMessages; tszBody += tszFwdMessages; } CMString tszAttachmentDescr; const JSONNode &jnAttachments = jnMsg["attachments"]; if (jnAttachments) { tszAttachmentDescr = GetAttachmentDescr(jnAttachments, m_vkOptions.BBCForAttachments()); if (!tszBody.IsEmpty()) tszBody += _T("\n"); tszBody += tszAttachmentDescr; } MCONTACT hContact = NULL; int chat_id = jnMsg["chat_id"].as_int(); 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); } if (chat_id != 0) { debugLogA("CVkProto::OnReceiveMessages chat_id != 0"); CMString action_chat = jnMsg["action"].as_mstring(); int action_mid = _ttoi(jnMsg["action_mid"].as_mstring()); if ((action_chat == "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"); AppendChatMessage(chat_id, jnMsg, jnFUsers, false); } continue; } PROTORECVEVENT recv = { 0 }; bool bUseServerReadFlag = m_vkOptions.bSyncReadMessageStatusFromServer ? true : !m_vkOptions.bMesAsUnread; if (isRead && bUseServerReadFlag) recv.flags |= PREF_CREATEREAD; if (isOut) recv.flags |= PREF_SENT; else if (m_vkOptions.bUserForceInvisibleOnActivity && time(NULL) - datetime < 60 * m_vkOptions.iInvisibleInterval) SetInvisible(hContact); T2Utf pszBody(tszBody); recv.timestamp = m_vkOptions.bUseLocalTime ? time(NULL) : datetime; recv.szMessage = pszBody; recv.lParam = isOut; recv.pCustomData = szMid; recv.cbCustomDataSize = (int)mir_strlen(szMid); Sleep(100); debugLogA("CVkProto::OnReceiveMessages mid = %d, datetime = %d, isOut = %d, isRead = %d, uid = %d", mid, datetime, isOut, isRead, uid); if (!CheckMid(m_sendIds, mid)) { debugLogA("CVkProto::OnReceiveMessages ProtoChainRecvMsg"); ProtoChainRecvMsg(hContact, &recv); if (mid > getDword(hContact, "lastmsgid", -1)) setDword(hContact, "lastmsgid", mid); if (!isOut) m_incIds.insert((HANDLE)mid); } else if (m_vkOptions.bLoadSentAttachments && !tszAttachmentDescr.IsEmpty() && isOut) { T2Utf pszAttach(tszAttachmentDescr); recv.timestamp = time(NULL); // only local time recv.szMessage = pszAttach; ProtoChainRecvMsg(hContact, &recv); } } if (!mids.IsEmpty()) MarkMessagesRead(mids); }
void CVkProto::OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveHistoryMessages %d", reply->resultCode); if (reply->resultCode != 200 || !pReq->pUserInfo) return; JSONNode jnRoot; CVkSendMsgParam *param = (CVkSendMsgParam*)pReq->pUserInfo; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse) { if (!pReq->bNeedsRestart || m_bTerminated) { delete param; pReq->pUserInfo = NULL; } return; } int iTime = jnResponse["datetime"].as_int(); const JSONNode &jnMsgs = jnResponse["items"]; const JSONNode &jnFUsers = jnResponse["fwd_users"]; int iLastMsgId = getDword(param->hContact, "lastmsgid", -1); time_t tLastReadMessageTime = 0; int count = 0; for (auto it = jnMsgs.rbegin(); it != jnMsgs.rend(); ++it) { const JSONNode &jnMsg = (*it); int mid = jnMsg["id"].as_int(); if (iLastMsgId < mid) iLastMsgId = mid; char szMid[40]; _itoa(mid, szMid, 10); CMString tszBody(jnMsg["body"].as_mstring()); int datetime = jnMsg["date"].as_int(); int isOut = jnMsg["out"].as_int(); int isRead = jnMsg["read_state"].as_int(); int uid = jnMsg["user_id"].as_int(); const JSONNode &jnFwdMessages = jnMsg["fwd_messages"]; if (jnFwdMessages) { CMString tszFwdMessages = GetFwdMessages(jnFwdMessages, jnFUsers, m_iBBCForAttachments); if (!tszBody.IsEmpty()) tszFwdMessages = _T("\n") + tszFwdMessages; tszBody += tszFwdMessages; } const JSONNode &jnAttachments = jnMsg["attachments"]; if (jnAttachments) { CMString tszAttachmentDescr = GetAttachmentDescr(jnAttachments, m_iBBCForAttachments); if (!tszBody.IsEmpty()) tszAttachmentDescr = _T("\n") + tszAttachmentDescr; tszBody += tszAttachmentDescr; } T2Utf pszBody(tszBody); MCONTACT hContact = FindUser(uid, true); PROTORECVEVENT recv = { 0 }; if (isRead) recv.flags |= PREF_CREATEREAD; if (isOut) recv.flags |= PREF_SENT; recv.timestamp = datetime; recv.szMessage = pszBody; recv.lParam = isOut; recv.pCustomData = szMid; recv.cbCustomDataSize = (int)mir_strlen(szMid); ProtoChainRecvMsg(hContact, &recv); if (isRead && isOut && datetime > tLastReadMessageTime) tLastReadMessageTime = datetime; count++; } setDword(param->hContact, "lastmsgid", iLastMsgId); if (ServiceExists(MS_MESSAGESTATE_UPDATE)) { MessageReadData data(tLastReadMessageTime, MRD_TYPE_MESSAGETIME); CallService(MS_MESSAGESTATE_UPDATE, param->hContact, (LPARAM)&data); } int once = jnResponse["once"].as_int(); int iRCount = jnResponse["rcount"].as_int(); if (count == iRCount && once == 0) GetServerHistory(param->hContact, param->iCount + count, iRCount, iTime, param->iMsgID); if (!pReq->bNeedsRestart || m_bTerminated) { delete param; pReq->pUserInfo = NULL; } }
void CVkProto::OnReceiveHistoryMessages(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveHistoryMessages %d", reply->resultCode); if (reply->resultCode != 200 || !pReq->pUserInfo) { mir_cslock lck(m_csLoadHistoryTask); if (m_iLoadHistoryTask > 0) m_iLoadHistoryTask--; debugLog(_T("CVkProto::OnReceiveHistoryMessages error m_iLoadHistoryTask=%d"), m_iLoadHistoryTask); MsgPopup(NULL, TranslateT("Error loading message history from server"), TranslateT("Error"), true); if (m_iLoadHistoryTask == 0 && m_bNotifyForEndLoadingHistoryAllContact) { MsgPopup(NULL, TranslateT("Loading messages for all contacts is completed"), TranslateT("Loading history")); m_bNotifyForEndLoadingHistoryAllContact = m_bNotifyForEndLoadingHistory = false; } return; } JSONNode jnRoot; CVkSendMsgParam *param = (CVkSendMsgParam*)pReq->pUserInfo; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse) { if (!pReq->bNeedsRestart || m_bTerminated) { mir_cslock lck(m_csLoadHistoryTask); if (m_iLoadHistoryTask > 0) m_iLoadHistoryTask--; ptrT ptszNick(db_get_tsa(param->hContact, m_szModuleName, "Nick")); CMString str(FORMAT, _T("%s %s %s"), TranslateT("Error loading message history from server"), TranslateT("for"), ptszNick); MsgPopup(param->hContact, str, TranslateT("Error"), true); debugLog(_T("CVkProto::OnReceiveHistoryMessages error for %s m_iLoadHistoryTask=%d"), ptszNick, m_iLoadHistoryTask); if (m_iLoadHistoryTask == 0 && m_bNotifyForEndLoadingHistoryAllContact) { MsgPopup(NULL, TranslateT("Loading messages for all contacts is completed"), TranslateT("Loading history")); m_bNotifyForEndLoadingHistoryAllContact = m_bNotifyForEndLoadingHistory = false; } delete param; pReq->pUserInfo = NULL; } return; } int iTime = jnResponse["datetime"].as_int(); const JSONNode &jnMsgs = jnResponse["items"]; const JSONNode &jnFUsers = jnResponse["fwd_users"]; int iLastMsgId = getDword(param->hContact, "lastmsgid", -1); time_t tLastReadMessageTime = 0; int count = 0; for (auto it = jnMsgs.rbegin(); it != jnMsgs.rend(); ++it) { const JSONNode &jnMsg = (*it); int mid = jnMsg["id"].as_int(); if (iLastMsgId < mid) iLastMsgId = mid; char szMid[40]; _itoa(mid, szMid, 10); CMString tszBody(jnMsg["body"].as_mstring()); int datetime = jnMsg["date"].as_int(); int isOut = jnMsg["out"].as_int(); int isRead = jnMsg["read_state"].as_int(); int uid = jnMsg["user_id"].as_int(); const JSONNode &jnFwdMessages = jnMsg["fwd_messages"]; if (jnFwdMessages) { CMString tszFwdMessages = GetFwdMessages(jnFwdMessages, jnFUsers, m_vkOptions.BBCForAttachments()); if (!tszBody.IsEmpty()) tszFwdMessages = _T("\n") + tszFwdMessages; tszBody += tszFwdMessages; } const JSONNode &jnAttachments = jnMsg["attachments"]; if (jnAttachments) { CMString tszAttachmentDescr = GetAttachmentDescr(jnAttachments, m_vkOptions.BBCForAttachments()); if (!tszBody.IsEmpty()) tszAttachmentDescr = _T("\n") + tszAttachmentDescr; tszBody += tszAttachmentDescr; } T2Utf pszBody(tszBody); MCONTACT hContact = FindUser(uid, true); PROTORECVEVENT recv = { 0 }; if (isRead) recv.flags |= PREF_CREATEREAD; if (isOut) recv.flags |= PREF_SENT; recv.timestamp = datetime; recv.szMessage = pszBody; recv.lParam = isOut; recv.pCustomData = szMid; recv.cbCustomDataSize = (int)mir_strlen(szMid); ProtoChainRecvMsg(hContact, &recv); if (isRead && isOut && datetime > tLastReadMessageTime) tLastReadMessageTime = datetime; count++; } setDword(param->hContact, "lastmsgid", iLastMsgId); if (ServiceExists(MS_MESSAGESTATE_UPDATE)) { MessageReadData data(tLastReadMessageTime, MRD_TYPE_MESSAGETIME); CallService(MS_MESSAGESTATE_UPDATE, param->hContact, (LPARAM)&data); } int once = jnResponse["once"].as_int(); int iRCount = jnResponse["rcount"].as_int(); if (count == iRCount && once == 0) GetServerHistory(param->hContact, param->iCount + count, iRCount, iTime, param->iMsgID); else { mir_cslock lck(m_csLoadHistoryTask); if (m_iLoadHistoryTask > 0) m_iLoadHistoryTask--; ptrT ptszNick(db_get_tsa(param->hContact, m_szModuleName, "Nick")); CMString str(FORMAT, TranslateT("Loading messages for %s is completed"), ptszNick); debugLog(_T("CVkProto::OnReceiveHistoryMessages for %s m_iLoadHistoryTask=%d"), ptszNick, m_iLoadHistoryTask); if (m_bNotifyForEndLoadingHistory) MsgPopup(param->hContact, str, TranslateT("Loading history")); if (m_iLoadHistoryTask == 0 && m_bNotifyForEndLoadingHistoryAllContact) { MsgPopup(NULL, TranslateT("Loading messages for all contacts is completed"), TranslateT("Loading history")); m_bNotifyForEndLoadingHistoryAllContact = m_bNotifyForEndLoadingHistory = false; } } if (!pReq->bNeedsRestart || m_bTerminated) { delete param; pReq->pUserInfo = NULL; } }