void CVkProto::AddFeedSpecialUser() { bool bSpecialContact = m_bNewsEnabled || m_bNotificationsEnabled || m_bSpecialContactAlwaysEnabled; MCONTACT hContact = FindUser(VK_FEED_USER); if (!bSpecialContact) { if (hContact) CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact); return; } if (!hContact) { hContact = FindUser(VK_FEED_USER, true); setTString(hContact, "Nick", TranslateT("VKontakte")); CMString tszUrl = _T("https://vk.com/press/Simple.png"); SetAvatarUrl(hContact, tszUrl); ReloadAvatarInfo(hContact); setTString(hContact, "domain", _T("feed")); setTString(hContact, "Homepage", _T("https://vk.com/feed")); } if (getWord(hContact, "Status") != ID_STATUS_ONLINE) setWord(hContact, "Status", ID_STATUS_ONLINE); SetMirVer(hContact, 7); }
void CVkProto::OnReceiveFriends(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveFriends %d", reply->resultCode); if (reply->resultCode != 200 || !IsOnline()) return; JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse) return; CVkSendMsgParam *param = (CVkSendMsgParam *)pReq->pUserInfo; bool bCleanContacts = getBool("AutoClean") || (param->iMsgID != 0); delete param; LIST<void> arContacts(10, PtrKeySortT); for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) { if (!isChatRoom(hContact)) setByte(hContact, "Auth", 1); db_unset(hContact, m_szModuleName, "ReqAuth"); SetMirVer(hContact, -1); if (bCleanContacts && !isChatRoom(hContact)) arContacts.insert((HANDLE)hContact); } const JSONNode &jnItems = jnResponse["items"]; if (jnItems) for (auto it = jnItems.begin(); it != jnItems.end(); ++it) { MCONTACT hContact = SetContactInfo((*it), true); if (hContact == NULL || hContact == INVALID_CONTACT_ID) continue; arContacts.remove((HANDLE)hContact); setByte(hContact, "Auth", 0); } if (bCleanContacts) for (int i = 0; i < arContacts.getCount(); i++) { MCONTACT hContact = (UINT_PTR)arContacts[i]; LONG userID = getDword(hContact, "ID", -1); if (userID == m_myUserId || userID == VK_FEED_USER) continue; CallService(MS_DB_CONTACT_DELETE, (WPARAM)hContact); } arContacts.destroy(); }
void CVkProto::OnReceiveUserInfo(NETLIBHTTPREQUEST *reply, AsyncHttpRequest *pReq) { debugLogA("CVkProto::OnReceiveUserInfo %d", reply->resultCode); if (reply->resultCode != 200 || !IsOnline()) return; JSONNode jnRoot; const JSONNode &jnResponse = CheckJsonResponse(pReq, reply, jnRoot); if (!jnResponse) return; const JSONNode &jnUsers = jnResponse["users"]; if (!jnUsers) return; if (!jnResponse["norepeat"].as_bool() && jnResponse["usercount"].as_int() == 0) { RetrieveUsersInfo(true, true); return; } MCONTACT hContact; LIST<void> arContacts(10, PtrKeySortT); for (hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) if (!isChatRoom(hContact)) arContacts.insert((HANDLE)hContact); for (auto it = jnUsers.begin(); it != jnUsers.end(); ++it) { hContact = SetContactInfo((*it)); if (hContact) arContacts.remove((HANDLE)hContact); } if (jnResponse["freeoffline"].as_bool()) for (int i = 0; i < arContacts.getCount(); i++) { hContact = (UINT_PTR)arContacts[i]; LONG userID = getDword(hContact, "ID", -1); if (userID == m_myUserId || userID == VK_FEED_USER) continue; int iContactStatus = getWord(hContact, "Status", ID_STATUS_OFFLINE); if ((iContactStatus == ID_STATUS_ONLINE) || (iContactStatus == ID_STATUS_INVISIBLE && time(NULL) - getDword(hContact, "InvisibleTS", 0) >= m_iInvisibleInterval * 60LL)) { setWord(hContact, "Status", ID_STATUS_OFFLINE); SetMirVer(hContact, -1); db_unset(hContact, m_szModuleName, "ListeningTo"); } } arContacts.destroy(); AddFeedSpecialUser(); const JSONNode &jnRequests = jnResponse["requests"]; if (!jnRequests) return; int iCount = jnRequests["count"].as_int(); const JSONNode &jnItems = jnRequests["items"]; if (!iCount || !jnItems) return; debugLogA("CVkProto::OnReceiveUserInfo AuthRequests"); for (auto it = jnItems.begin(); it != jnItems.end(); ++it) { LONG userid = (*it).as_int(); if (userid == 0) break; hContact = FindUser(userid, true); if (!getBool(hContact, "ReqAuth")) { RetrieveUserInfo(userid); setByte(hContact, "ReqAuth", 1); ForkThread(&CVkProto::DBAddAuthRequestThread, (void *)hContact); } } }
MCONTACT CVkProto::SetContactInfo(const JSONNode &jnItem, bool flag, bool self) { if (!jnItem) { debugLogA("CVkProto::SetContactInfo pItem == NULL"); return INVALID_CONTACT_ID; } LONG userid = jnItem["id"].as_int(); debugLogA("CVkProto::SetContactInfo %d", userid); if (userid == 0 || userid == VK_FEED_USER) return NULL; MCONTACT hContact = FindUser(userid, flag); if (userid == m_myUserId) { if (hContact != NULL) if (self) hContact = NULL; else SetContactInfo(jnItem, flag, true); } else if (hContact == NULL) return NULL; CMString tszNick, tszValue; int iValue; tszValue = jnItem["first_name"].as_mstring(); if (!tszValue.IsEmpty()) { setTString(hContact, "FirstName", tszValue); tszNick.Append(tszValue); tszNick.AppendChar(' '); } tszValue = jnItem["last_name"].as_mstring(); if (!tszValue.IsEmpty()) { setTString(hContact, "LastName", tszValue); tszNick.Append(tszValue); } if (!tszNick.IsEmpty()) setTString(hContact, "Nick", tszNick); int sex = jnItem["sex"].as_int(); if (sex) setByte(hContact, "Gender", sex == 2 ? 'M' : 'F'); tszValue = jnItem["bdate"].as_mstring(); if (!tszValue.IsEmpty()) { int d, m, y, iReadCount; iReadCount = _stscanf(tszValue, _T("%d.%d.%d"), &d, &m, &y); if (iReadCount > 1) { if (iReadCount == 3) setWord(hContact, "BirthYear", y); setByte(hContact, "BirthDay", d); setByte(hContact, "BirthMonth", m); } } tszValue = jnItem["photo_100"].as_mstring(); if (!tszValue.IsEmpty()) { SetAvatarUrl(hContact, tszValue); ReloadAvatarInfo(hContact); } int iNewStatus = (jnItem["online"].as_int() == 0) ? ID_STATUS_OFFLINE : ID_STATUS_ONLINE; if (getWord(hContact, "Status", ID_STATUS_OFFLINE) != iNewStatus) setWord(hContact, "Status", iNewStatus); if (iNewStatus == ID_STATUS_ONLINE) { int online_app = _ttoi(jnItem["online_app"].as_mstring()); int online_mobile = jnItem["online_mobile"].as_int(); if (online_app == 0 && online_mobile == 0) SetMirVer(hContact, 7); // vk.com else if (online_app != 0) SetMirVer(hContact, online_app); // App else SetMirVer(hContact, 1); // m.vk.com } else SetMirVer(hContact, -1); // unset MinVer if ((iValue = jnItem["timezone"].as_int()) != 0) setByte(hContact, "Timezone", iValue * -2); tszValue = jnItem["mobile_phone"].as_mstring(); if (!tszValue.IsEmpty()) setTString(hContact, "Cellular", tszValue); tszValue = jnItem["home_phone"].as_mstring(); if (!tszValue.IsEmpty()) setTString(hContact, "Phone", tszValue); tszValue = jnItem["status"].as_mstring(); CMString tszOldStatus(ptrT(db_get_tsa(hContact, hContact ? "CList" : m_szModuleName, "StatusMsg"))); if (tszValue != tszOldStatus) db_set_ts(hContact, hContact ? "CList" : m_szModuleName, "StatusMsg", tszValue); CMString tszOldListeningTo(ptrT(db_get_tsa(hContact, m_szModuleName, "ListeningTo"))); const JSONNode &jnAudio = jnItem["status_audio"]; if (jnAudio) { CMString tszListeningTo(FORMAT, _T("%s - %s"), jnAudio["artist"].as_mstring(), jnAudio["title"].as_mstring()); if (tszListeningTo != tszOldListeningTo) { setTString(hContact, "ListeningTo", tszListeningTo); setTString(hContact, "AudioUrl", jnAudio["url"].as_mstring()); } } else if (tszValue[0] == TCHAR(9835) && tszValue.GetLength() > 2) { setTString(hContact, "ListeningTo", &(tszValue.GetBuffer())[2]); db_unset(hContact, m_szModuleName, "AudioUrl"); } else { db_unset(hContact, m_szModuleName, "ListeningTo"); db_unset(hContact, m_szModuleName, "AudioUrl"); } tszValue = jnItem["about"].as_mstring(); if (!tszValue.IsEmpty()) setTString(hContact, "About", tszValue); tszValue = jnItem["domain"].as_mstring(); if (!tszValue.IsEmpty()) { setTString(hContact, "domain", tszValue); CMString tszUrl("https://vk.com/"); tszUrl.Append(tszValue); setTString(hContact, "Homepage", tszUrl); } return hContact; }
void CVkProto::PollUpdates(const JSONNode &jnUpdates) { debugLogA("CVkProto::PollUpdates"); CMStringA mids; int msgid, uid, flags, platform; MCONTACT hContact; for (auto it = jnUpdates.begin(); it != jnUpdates.end(); ++it) { const JSONNode &jnChild = (*it).as_array(); switch (jnChild[json_index_t(0)].as_int()) { case VKPOLL_MSG_DELFLAGS: if (jnChild.size() < 4) break; msgid = jnChild[1].as_int(); flags = jnChild[2].as_int(); uid = jnChild[3].as_int(); hContact = FindUser(uid); if (hContact != NULL && (flags & VKFLAG_MSGUNREAD) && !CheckMid(m_incIds, msgid)) { setDword(hContact, "LastMsgReadTime", time(NULL)); if (ServiceExists(MS_MESSAGESTATE_UPDATE)) { MessageReadData data(time(NULL), MRD_TYPE_READTIME); CallService(MS_MESSAGESTATE_UPDATE, hContact, (LPARAM)&data); } else SetSrmmReadStatus(hContact); if (m_bUserForceOnlineOnActivity) SetInvisible(hContact); if (m_bSyncReadMessageStatusFromServer) MarkDialogAsRead(hContact); } break; case VKPOLL_MSG_ADDED: // new message msgid = jnChild[1].as_int(); // skip outgoing messages sent from a client flags = jnChild[2].as_int(); if (flags & VKFLAG_MSGOUTBOX && !(flags & VKFLAG_MSGCHAT) && CheckMid(m_sendIds, msgid)) break; if (!mids.IsEmpty()) mids.AppendChar(','); mids.AppendFormat("%d", msgid); break; case VKPOLL_READ_ALL_OUT: uid = jnChild[1].as_int(); hContact = FindUser(uid); if (hContact != NULL) { setDword(hContact, "LastMsgReadTime", time(NULL)); if (ServiceExists(MS_MESSAGESTATE_UPDATE)) { MessageReadData data(time(NULL), MRD_TYPE_READTIME); CallService(MS_MESSAGESTATE_UPDATE, hContact, (LPARAM)&data); } else SetSrmmReadStatus(hContact); if (m_bUserForceOnlineOnActivity) SetInvisible(hContact); } break; case VKPOLL_READ_ALL_IN: uid = jnChild[1].as_int(); hContact = FindUser(uid); if (hContact != NULL && m_bSyncReadMessageStatusFromServer) MarkDialogAsRead(hContact); break; case VKPOLL_USR_ONLINE: uid = -jnChild[1].as_int(); if ((hContact = FindUser(uid)) != NULL) { setWord(hContact, "Status", ID_STATUS_ONLINE); platform = jnChild[2].as_int(); SetMirVer(hContact, platform); } break; case VKPOLL_USR_OFFLINE: uid = -jnChild[1].as_int(); if ((hContact = FindUser(uid)) != NULL) { setWord(hContact, "Status", ID_STATUS_OFFLINE); db_unset(hContact, m_szModuleName, "ListeningTo"); SetMirVer(hContact, -1); } break; case VKPOLL_USR_UTN: uid = jnChild[1].as_int(); hContact = FindUser(uid); if (hContact != NULL) { ForkThread(&CVkProto::ContactTypingThread, (void *)hContact); if (m_bUserForceOnlineOnActivity) SetInvisible(hContact); } break; case VKPOLL_CHAT_UTN: ForkThread(&CVkProto::ChatContactTypingThread, new CVKChatContactTypingParam(jnChild[2].as_int(), jnChild[1].as_int())); break; case VKPOLL_CHAT_CHANGED: int chat_id = jnChild[1].as_int(); CVkChatInfo *cc = m_chats.find((CVkChatInfo*)&chat_id); if (cc) RetrieveChatInfo(cc); break; } } RetrieveMessagesByIds(mids); }